次のコード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
ジェネリックにしたいのですが、使用法とは別にファイルに入れると、値制限エラーが発生します。
値制限。'_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"]
行動が変わるのはなぜ?関数をジェネリックにして、目的の動作を実現するにはどうすればよいですか?