このコードの問題は誰か知っていますか?
let rec Foo(a,b) =
match a () with
| None -> Some(b)
| Some(c) -> Some(Foo(c,b))
コンパイラエラーは次のとおりです。
"タイプの不一致。'aが必要ですが、'aオプションが指定されています。''a'と''aオプション'を統合すると、結果のタイプは無限になります。"
このコードの問題は誰か知っていますか?
let rec Foo(a,b) =
match a () with
| None -> Some(b)
| Some(c) -> Some(Foo(c,b))
コンパイラエラーは次のとおりです。
"タイプの不一致。'aが必要ですが、'aオプションが指定されています。''a'と''aオプション'を統合すると、結果のタイプは無限になります。"
ここで、コンパイラが型を推測しようとする方法を再現してみましょう。
let rec Foo(a,b) =
match a () with
| None -> Some(b)
| Some(c) -> Some(Foo(c,b))
「わかりa ()
ました。あるタイプa
の関数である必要があります。unit
どちらのタイプかはまだわかりません。これを呼び出します'a
。」
a : unit -> 'a
「の結果は/パターンa ()
と一致します。したがって、aである必要があり、タイプはです。」(繰り返しますが、まだ不明なタイプを表します)。None
Some
'a
'b option
c
'b
'b
a : unit -> 'b option
с : 'b
「関数やメソッドは呼び出されません(タイプを絞り込まない、および、これまでのところタイプがわからないタイプをb
除く)。そのタイプを。で示します。」Some
Foo
'c
a : unit -> 'b option
b : 'c
c : 'b
「ブランチの1つでFoo
戻るSome(b)
ため、戻りタイプは。である必要があります'c option
。」
Foo : (unit -> 'b option) * 'c -> 'c option
「もう完了しましたか?いいえ、式のすべての型が意味をなすかどうかを確認する必要があります。Some(c)
場合によっては、Some(Foo(c,b))
が返されることを確認してください。したがって、が返されるFoo(c,b) : 'c
ので、いくつかの必要があることがわかります。持っている、つまり。と同じタイプである必要がありますが、これは不可能です!定義にエラーがあるはずです。報告する必要があります。」そうです。Foo
option
'c
'd option
'd
b : 'd
b : 'c
b : 'd option
'd
'd option
それは常に物事を段階的に分解するのに役立ちます。書かれているように、Fooのタイプは次のとおりです。
val Foo : (unit -> 'a option) * 'b -> 'b option
アクティブなパターンの各式は、同じタイプに評価される必要があります。式の最初のパターンマッチのタイプは次のとおりです。
'b option
したがって、他のパターンも'b option
またはに評価する必要があり'a option
ます。あなたがここにそれを持っている方法、それは戻ってい'a option option
ます。
これは独特の関数ですが、2番目のパターンマッチで任意のオプション値を返すことでコンパイラエラーを修正できます。これが私が考えることができる唯一の例で、上記のように見えます。
let Foo2(a,b) =
match a () with
| None -> Some(b)
| c -> c
HTH。
a()
の最初のパラメーターであるオプションとして使用していますFoo
が、最後の行c
には型がありますが、それを再帰呼び出しに渡します。
それがエラーの原因です。
c
オプション型にする必要があります。