2

このコードの問題は誰か知っていますか?

let rec Foo(a,b) =
    match a () with
    | None -> Some(b)
    | Some(c) -> Some(Foo(c,b))

コンパイラエラーは次のとおりです。

"タイプの不一致。'aが必要ですが、'aオプションが指定されています。''a'と''aオプション'を統合すると、結果のタイプは無限になります。"

4

3 に答える 3

8

ここで、コンパイラが型を推測しようとする方法を再現してみましょう。

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である必要があり、タイプはです。」(繰り返しますが、まだ不明なタイプを表します)。NoneSome'a'b optionc'b'b

a : unit -> 'b option
с : 'b

「関数やメソッドは呼び出されません(タイプを絞り込まない、および、これまでのところタイプがわからないタイプをb除く)。そのタイプを。で示します。」SomeFoo'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ので、いくつかの必要があることがわかります。持っている、つまり。と同じタイプである必要がありますが、これは不可能です!定義にエラーがあるはずです。報告する必要があります。」そうです。Foooption'c'd option'db : 'db : 'cb : 'd option'd'd option

于 2009-12-29T13:00:25.493 に答える
4

それは常に物事を段階的に分解するのに役立ちます。書かれているように、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。

于 2009-12-29T02:42:14.213 に答える
1

a()の最初のパラメーターであるオプションとして使用していますFooが、最後の行cには型がありますが、それを再帰呼び出しに渡します。

それがエラーの原因です。

cオプション型にする必要があります。

于 2009-12-29T01:22:27.400 に答える