在以下代码中,Seq.generateUnique
被限制为((Assembly -> seq<Assembly>) -> seq<Assembly> -> seq<Assembly>)
类型。
open System
open System.Collections.Generic
open System.Reflection
module Seq =
let generateUnique =
let known = HashSet()
fun f initial ->
let rec loop items =
seq {
let cachedSeq = items |> Seq.filter known.Add |> Seq.cache
if not (cachedSeq |> Seq.isEmpty) then
yield! cachedSeq
yield! loop (cachedSeq |> Seq.collect f)
}
loop initial
let discoverAssemblies() =
AppDomain.CurrentDomain.GetAssemblies() :> seq<_>
|> Seq.generateUnique (fun asm -> asm.GetReferencedAssemblies() |> Seq.map Assembly.Load)
let test() = printfn "%A" (discoverAssemblies() |> Seq.truncate 2 |> Seq.map (fun asm -> asm.GetName().Name) |> Seq.toList)
for _ in 1 .. 5 do test()
System.Console.Read() |> ignore
我希望它是通用的,但是将其放入文件中除了它的使用之外会产生值限制错误:
价值限制。价值 'generateUnique'已被推断出来 有通用类型val generateUnique:(('_a - &gt;'_ b) - &gt;'_ c - &GT;当'_b:&gt;时,seq&lt;'_ a&gt;) SEQ&LT;'_ A&GT;和'_c:&gt; SEQ&LT;'_ A&GT;要么成功 “generateUnique”的参数是显式的 或者,如果你不打算这样做的话 通用,添加类型注释。
添加显式类型参数(let generateUnique<'T> = ...
)可消除错误,但现在返回不同的结果。
没有类型参数的输出(所需/正确的行为):
["mscorlib"; "TEST"]
["FSharp.Core"; "System"]
["System.Core"; "System.Security"]
[]
[]
并且:
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
为什么行为改变了?我怎样才能使函数泛型和实现所需的行为?
答案 0 :(得分:3)
我不认为你的定义是正确的:在我看来f
需要成为generateUnique
的句法论证(也就是说,我不相信它是有道理的对不同的HashSet
使用相同的f
。因此,一个简单的解决方法是:
let generateUnique f =
let known = HashSet()
fun initial ->
let rec loop items =
seq {
let cachedSeq = items |> Seq.filter known.Add |> Seq.cache
if not (cachedSeq |> Seq.isEmpty) then
yield! cachedSeq
yield! loop (cachedSeq |> Seq.collect f)
}
loop initial
答案 1 :(得分:3)
generateUnique
与标准memoize
模式非常相似:它应该用于从正常函数计算memoized函数,而不是实际缓存本身。
@kvb关于此转变所需定义的更改是正确的,但是您需要更改discoverAssemblies
的定义,如下所示:
let discoverAssemblies =
//"memoize"
let generator = Seq.generateUnique (fun (asm:Assembly) -> asm.GetReferencedAssemblies() |> Seq.map Assembly.Load)
fun () ->
AppDomain.CurrentDomain.GetAssemblies() :> seq<_>
|> generator