7

タプルの自明なシーケンスと、F# PowerPack の PSeq を使用した並列シーケンスがあるとします。

let a = Seq.singleton (1,"a")  --> val a: seq<int * string>
let b = a |> PSeq.map id       --> val b: pseq<int * string>

ここで、それらから .Net BCL ディクショナリを作成したいと思います。

let bd = b.ToDictionary(fst, snd, HashIdentity.Structural)
let ad = a.ToDictionary(fst, snd, HashIdentity.Structural)
let ad2 = a.ToDictionary(fst, snd)
let ad3 = a.ToDictionary((fun (x,y) -> x), (fun (x,y) -> y), HashIdentity.Structural)

let bd動作しlet adますが、型を推測して BCL の Func に正しく変換できないため、コンパイルされません。興味深いことに、 のように 3 番目のパラメーターを省略しlet ad2たり、 のように手動でインライン化したりするfstと、問題なく動作します。sndlet ad3

この式は Func<(int * string),'a> 型を持つことが期待されていましたが、ここでは 'b * 'c -> 'b 型になっています

  • すべての代替手段が正常に機能するのに、なぜlet adコンパイルしないのですか?
  • let adインライン関数や型注釈を提供せずにコンパイルする方法はありますか?

PS: HashIdentity.Structural が必要です。実際のコードでは、キーは整数ではなくタプルまたはレコードであるためです。

更新: を定義let dictionary (s : ('a * 'b) seq) = s.ToDictionary((fun (x,y)->x), (fun (x,y)->y), HashIdentity.Structural)したので、 と書けるようになりましたが、および関数let ad = a |> dictionaryでコンパイルされない理由にまだ興味があります。fstsnd

4

2 に答える 2

9

これは正確にはバグではなく、F# の型推論アルゴリズムの、オーバーロードと型指定変換が関係する非常に見苦しいケースに過ぎないと思います。奇妙なことに、 2 つの引数を持つの 2 番目のオーバーロードが存在するため、コンパイラはad2バインディングの型を正しく推測します。これにより、推論中に追加のオーバーロード解決ステップが発生します。ToDictionary一方、3 つの引数を持つオーバーロードは 1 つしかないため、adの型を推測しようとするときにオーバーロードの解決手順は使用されません。

前述したように、パズルのもう 1 つのピースは、F# 関数から .NET デリゲート型への型指定変換です (これは、aFunc<_,_>が必要な場所に F# 関数を渡す方法です)。基本的に、明示的なラムダを使用する場合、または複数のオーバーロードがある場合、この変換は考慮されますが、オーバーロードが 1 つだけで明示的なラムダがない場合、変換は考慮されません。これは、以下も機能することを意味します。

let ad3 = a.ToDictionary(System.Func<_,_>(fst), 
                         System.Func<_,_>(snd), HashIdentity.Structural)

型指定変換を実行する必要がなくなったからです。

この結果は確かに直観に反しているので、型推論アルゴリズムを微調整して、これらのコーナー ケースをより適切に処理する方法があることを願っています。残念ながら、.NET 型システムの特定の側面 (名前付きデリゲート型、サブタイピング、オーバーロードなど) と相互運用すると、推論が他の場合よりもはるかに難しくなり、アルゴリズムが簡単に実行できない理由がいくつかある可能性があります。このケースを処理するように変更されました。

于 2012-10-17T14:49:56.470 に答える
2

バグ (または過負荷解決のエッジ ケース) のように見えますが、組み込みdict関数を使用して問題を回避できます。

let a = Seq.singleton (1,"a")  
let b = a |> PSeq.map id 
let bd = dict b
let ad = dict a
于 2012-10-17T14:17:10.460 に答える