2011-04-20 114 views

回答

1

seq<'T>類型是編寫適用於F#中任何集合的計算的主要方式。有您能與類型工作的幾種方法:

  • 您可以使用函數從Seq模塊(如Seq.filterSeq.windowed等)
  • 您可以使用序列內涵(如seq { for x in col -> x * 2 }
  • 您可以使用底層(勢在必行)IEnumerator<'T>類型,有時需要例如如果要實現自己的收藏夾壓縮(通過調用GetEnumerator返回)

這是相對簡單的類型,它只能用於從集合中讀取數據。因此,您將始終獲得類型爲seq<'T>的值,該值本質上是一個惰性序列。 F#沒有任何用於轉換集合的機制(例如,採用集合C到具有新值的集合C的通用函數)或用於創建集合(在Haskell或Scala中可用)的任何機制。

在大多數實際情況下,我沒有發現問題 - 大部分工作可以使用seq<'T>完成,當您需要專門的集合(例如數組用於性能)時,通常需要稍微不同的實現無論如何。

+0

謝謝你的回答。因此,如果我想保留關於我的原始集合的類型的信息(比如說,爲了避免在以後要將「Knuth shuffle」鏈接到手動拉鍊操作時被強制調用'Seq.toArray'),我必須咬子彈和複製粘貼zipWith我想支持的所有集合類型? – 2011-04-20 12:44:32

+1

@Alexander:是的,據我所知,完全不依賴於容器的算法(例如C++中)是不可能的。我想理論上可以在不同的集合類型周圍實現面向對象的包裝器......但這會值得嗎? - Wrt。到'zipWith':所有的收集模塊都支持'map2'函數。 – wmeyer 2011-04-20 16:19:50

+0

@wmeyer:謝謝。能夠獨立於容器實現編寫算法對我來說是一個很有價值的特性。據我所知,在大多數實際情況下,缺乏這種能力不是問題,我認爲我從根本上不了解如何構建F#代碼。 – 2011-04-20 18:17:27

2

集合的泛型編程可以像泛型編程一樣進行處理:使用泛型。

let f (map_fun : ('T1 -> 'T2) -> 'T1s -> 'T2s) (iter_fun : ('T2 -> unit) -> 'T2s -> unit) (ts : 'T1s) (g : 'T1 -> 'T2) (h : 'T2 -> unit)= 
    ts 
    |> map_fun g 
    |> iter_fun h 

type A = 
    static member F(ts, g, h) = f (Array.map) (Array.iter) ts g h 
    static member F(ts, g, h) = f (List.map) (List.iter) ts g h 

有點醜陋和冗長,但它是可能的。我正在使用類和靜態成員來利用重載。在你的代碼中,你可以使用A.F,並調用正確的專業化。

要獲得更漂亮的解決方案,請參見https://stackoverflow.com/questions/979084/what-features-would-you-add-remove-or-change-in-f/987569#987569儘管僅針對核心庫啓用了此功能,但修改編譯器以使其在您的代碼中不會出現問題。這是可能的,因爲編譯器的源代碼是打開的。

+0

謝謝,Joh。這確實很冗長。 – 2011-04-21 13:59:24