6

こんにちは、みなさん!

そのため、.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

それをseq<'a>に一般化しようとすると失敗します。これは、コンパイラーがその列挙子を静的に入力することを要求しているためです(これは理にかなっています)。

これを回避する方法はありますか?これは、機能的な方法で.NETデータ構造を使用する際の制限であると私は考え始めています。

これが初心者の質問である場合は申し訳ありません。私はF#と関数型プログラミング全般に関心があります(そしてそれが大好きです!)。乾杯!

  • カルロス。
4

2 に答える 2

12

Seq.castDanielが言うように、ほとんどのコレクションはすでにジェネリックseq<'t>インターフェイスを実装しているため、通常は使用する必要はありません。ただし、.NET 2.0でジェネリックが導入される前に構築されたいくつかの.NETコレクションタイプがあり、非ジェネリックIEnumerableインターフェイスのみを実装しています。F#コンパイラには、実際にはfor「列挙可能な抽出」と呼ばれるループ内の特別なロジックがあり、これらの種類のコレクションに対する作業が少し簡単になります。したがって、これらのコレクションタイプの1つだけを扱っている場合(たとえば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なり、正しいアイテムタイプが推測されます。ただし、これはおそらくあなたの場合はやり過ぎです。

于 2012-11-26T21:53:06.493 に答える
3

ほとんどの.NETコレクションはIEnumerable<T>(F#のようにエイリアスされseq<'T>て)実装されていますが、非ジェネリックインターフェイスのみを実装しているコレクションに出くわすこともありますIEnumerableSearchResultCollectionそのようなタイプの1つです。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
于 2012-11-26T21:08:29.473 に答える