Car*_*nez 6 .net f# functional-programming
大家下午好!
所以我一直在讨论将.NET Collection转换为功能数据结构的方法.我能得到的最好的就是先将它投射到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 *)
Run Code Online (Sandbox Code Playgroud)
为了对entries_list做任何有用的事情,我必须这样做:
entries_list :?> SearchResult
Run Code Online (Sandbox Code Playgroud)
试图将它推广到seq <'a>失败,因为编译器仍然要求我静态地键入其枚举器(这是有道理的).
有没有办法避免这种情况?我开始认为这是以功能方式使用.NET数据结构的限制.
对不起,如果这是一个新手问题; 我对F#和一般的函数式编程都很环保(我喜欢它!).干杯!
kvb*_*kvb 12
正如Daniel所说,您通常不需要使用,Seq.cast因为大多数集合已经实现了通用seq<'t>接口.但是,有几种.NET集合类型是在.NET 2.0中引入泛型之前构建的,它只实现了非泛型IEnumerable接口.F#编译器实际上在for循环中有一些称为"可枚举提取"的特殊逻辑,以便更容易地对付这些类型的集合.因此,如果您只处理其中一种集合类型(例如,您正在处理DirectoryServices.SearchResultCollections很多),那么简单地创建一个简单的辅助函数可能是有意义的:
let typedSearchResults (s:SearchResultCollection) =
seq { for result in s -> result }
Run Code Online (Sandbox Code Playgroud)
然后您可以使用它而不是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 }
Run Code Online (Sandbox Code Playgroud)
现在您可以使用Seq.inferCast而不是Seq.cast,并将为您推断出正确的项目类型.不过,这可能在你的情况下有点过分了.
| 归档时间: |
|
| 查看次数: |
1099 次 |
| 最近记录: |