在下面的代码Seq.generateUnique
中被限制为 type ((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 -> '_b) -> '_c -> seq<'_a>) 当 '_b :> seq<'_a> 和 '_c : > seq<'_a> 要么显式地设置 'generateUnique' 的参数,或者,如果你不打算让它是通用的,添加一个类型注解。
添加显式类型参数 ( let generateUnique<'T> = ...
) 可消除错误,但现在它返回不同的结果。
没有类型参数的输出(期望/正确的行为):
["mscorlib"; "TEST"]
["FSharp.Core"; "System"]
["System.Core"; "System.Security"]
[]
[]
与:
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
为什么行为会改变?我怎样才能使函数通用并实现所需的行为?