4

シナリオ 1

let map = Dictionary<string,obj>()
map.Add("1",10)
map.Add("2",10L)
map.Add("3","10")

これはうまく準拠しています

シナリオ 2

let map = Dictionary<string,(unit -> obj)>()
map.Add("1",fun() -> 10)
map.Add("2",fun() -> 10L)
map.Add("3",fun() -> "10")

ここで、コンパイラは obj を除外したが、遭遇したときに int を見つけたと言っています10

シナリオ 3

let map = Dictionary<string,(unit -> 'a)>()
map.Add("1",fun() -> 10)
map.Add("2",fun() -> 10L)
map.Add("3",fun() -> "10")

ここで、コンパイラは最初のエントリを受け入れますが、'a が int に制約され、次の 2 つのエントリは int ではないため失敗します。

1 番目の質問: シナリオ 2 ではコンパイルされないのに、シナリオ 1 ではコンパイルされるのはなぜですか?

2 番目の質問: 'a がシナリオ 3 で制約されるのを防ぐ方法はありますか、または F# のコレクションでさまざまな型 (具体的にはこの例のような関数型) を持つことを可能にする特定のパターンを使用できますか?

値 (obj / 'a) が使用される唯一のことは、println "%A"それができない理由がわからない引数であることです。

4

1 に答える 1

2

シナリオ 1では、コンパイラは引数をmap.Addfrom intetc に自動的にアップキャストしobjます。map.Addobj

シナリオ 2 では、unit -> inttoから利用できるアップキャストがないため、これを行うことができません。関数の前後にunit -> obj手動で挿入して変換を行うことはできませんでした。upcast

理論的には、コンパイラは代わりに関数の本体を変更できますが、キャストの自動挿入は、呼び出しが行われた時点で純粋にローカルmap.Addです。

シナリオ 3 で制約されることを防ぐことはできません'a。ランタイムでは、特定のオブジェクトが特定の型を持っている必要があるためです。値を特定の方法でしか使用しない場合でも、コンパイラとランタイムは、そのようなグローバルな分析を行いません。それを見る必要があります。

于 2013-06-04T15:27:54.803 に答える