2012-11-26 46 views
5

大家下午好!有沒有將Collection轉換爲F#序列的安全方法?

所以我一直在玩弄.NET集合到功能數據結構的方式。我已經能夠獲得的最好的結果是首先將它投射到seq,然後再投射到我想要的任何東西上。

問題是,這似乎打破了類型推斷,這顯然是不安全的。

例子:

let a = new System.DirectoryServices.DirectorySearcher("<query>") in 
let entries = a.FindAll() 
let entries_list = 
    let (entries_seq : seq<obj>) = Seq.cast entries_list in 
    Seq.toList entries_Seq 
in 
entries_list (* list of AD objects found from query, has type obj *) 

爲了做任何entries_list有用的,我不得不做的事:

entries_list :?> SearchResult 

試圖把它推廣到一個序列<「一>失敗,因爲編譯器仍然要求我靜態地鍵入它的枚舉器(這是有道理的)。

有什麼辦法可以避免這種情況?我開始認爲這是以功能方式使用.NET數據結構的限制。

對不起,如果這是一個新手的問​​題;我對F#和一般的函數式編程都是綠色的(我很喜歡它!)。乾杯!

  • Carlos。
+0

做'let entries_seq:seq <_> ...'工作 - 這應該給一個強類型的序列 –

+0

它沒有;我得到一個價值限制錯誤,這與我之前看到的一致。 –

回答

11

正如丹尼爾說,你通常應該不需要使用Seq.cast,因爲大部分藏品都已經實現通用seq<'t>接口。但是,有幾種.NET集合類型是在.NET 2.0中引入泛型之前構建的,它只實現非泛型的IEnumerable接口。 F#編譯器實際上在for循環中有一些特殊的邏輯,稱爲「枚舉抽取」,以使對這些類型的集合更容易一些。因此,如果你只使用這些集合類型之一(例如你與DirectoryServices.SearchResultCollections很多工作)的交易,那麼它很可能是有道理的,以簡單地創建一個簡單的輔助功能:

let typedSearchResults (s:SearchResultCollection) = 
    seq { for result in s -> result } 

,你可以再使用此特定集合類型代替Seq.cast

如果您使用許多不同的舊式集合在同一個項目,那麼你可以使用一些花哨的F#的功能,使通用Seq.cast選擇:

module Seq = 
    let inline inferCast s = 
     // constrain ^t to have an Item indexed property (which we don't actually invoke) 
     let _ = fun x -> (^t : (member Item : int -> ^v with get) (x, 0)) 
     let e = (^t : (member GetEnumerator : unit -> ^e) s) 
     seq { while (^e : (member MoveNext : unit -> bool) e) do 
       yield (^e : (member Current : obj) e) :?> ^v } 

現在你可以使用Seq.inferCast代替Seq.cast,並且會爲您推斷正確的項目類型。不過,這可能是過度殺傷你的情況。

+1

+1好玩,但你忘記了「內聯」。 – Daniel

+0

@丹尼爾 - 謝謝,修正。 – kvb

+0

這實際上可能正是我要找的。非常感謝! –

3

大多數.NET集合執行IEnumerable<T>(在F#別名爲seq<'T>),但偶爾你會跨越一個只實現非泛型接口IEnumerable運行。 SearchResultCollection就是這樣一種類型。您可以使用Seq.cast將這些集合轉換爲seq<'T>,從而可以將它們用於Seq模塊中的功能。

open System.DirectoryServices 

use searcher = new DirectorySearcher("<query>") 
let entries = searcher.FindAll() |> Seq.cast<SearchResult> 
let entries_list = Seq.toList entries 
+0

感謝您的快速響應! 我得到了那麼多,但我怎麼概括這個所有這樣的集合?這似乎是我不能不做大量的靜態類型。 卡洛斯 –

+0

你想'Seq.cast',但不需要類型arg?那麼,在很多情況下,它可以從序列的後續使用中推斷出來。 kvb給出了一個有趣的解決方案,但它也有一些限制。 – Daniel

相關問題