在下面的代碼中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
我想它是通用的,但把它變成一個文件,除了它的使用產生的值限制錯誤:
Value restriction. The value 'generateUnique' has been inferred to have generic type val generateUnique : (('_a -> '_b) -> '_c -> seq<'_a>) when '_b :> seq<'_a> and '_c :> seq<'_a> Either make the arguments to 'generateUnique' explicit or, if you do not intend for it to be generic, add a type annotation.
添加一個顯式類型參數(let generateUnique<'T> = ...
)消除錯誤,但現在它返回不同的結果。
輸出無類型參數(所需的/正確的行爲):
["mscorlib"; "TEST"]
["FSharp.Core"; "System"]
["System.Core"; "System.Security"]
[]
[]
而且具有:
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
爲什麼會發生行爲改變?我怎麼能使功能通用和達到預期的行爲?
爲什麼不使用Seq.distinctBy? – Huusom
@Huusom:這裏還有更多。這就像'獨特'+遞歸'收集'+記憶,它們之間有微妙的相互依賴關係。 – Daniel