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
私はそれが一般的なように好きですが、その使い方とは別にファイルにそれを置くことは値制限エラーを生成したい:明示的な型パラメータ(let generateUnique<'T> = ...
)を追加
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.
はエラーを排除しかし、今は別の結果を返します。 typeパラメータ(正しい/希望の動作)なし
出力:
["mscorlib"; "TEST"]
["FSharp.Core"; "System"]
["System.Core"; "System.Security"]
[]
[]
とと:
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
["mscorlib"; "TEST"]
なぜ行動変容していますか?どのようにして汎用機能とを目的の動作にすることができますか?
Seq.distinctByを使用しないのはなぜ? – Huusom
@Huusom:もう少し詳しいことがあります。それは、 'distinct' + recursive' collect' + memoizationのようなもので、それらの間に微妙な相互依存性があります。 – Daniel