10

計算式のメソッドに関する msdn ドキュメントには、次のように記載されています。Zero

計算式elseの式の空の分岐に対して呼び出されます。if...then

定義されidentityていない計算ビルダーを使用しているとします。Zero

let IdentityBuilder() = 
    member this.Bind(i, f) = f i
    member this.Return(i) = i

let identity = new IdentityBuilder()

以下のコードは許可されています

identity {
    printf "Hello World"
    return 1
}

ただし、次のコードは許可されておらず、コンパイラ エラーで失敗します。

この制御構造は、計算式ビルダーが「ゼロ」メソッドを定義する場合にのみ使用できます

identity {
    if true then printf "Hello World"
    return 1
}

コンパイラが分岐の呼び出しZeroを主張するのはなぜですか? elseこの背後にある直感は何ですか?

4

1 に答える 1

6

の実装Zeroが必要かどうかは、ifステートメントがモナド構文から関数呼び出しにどのように変換されるかによって決まります。an の両方の分岐ifが構文上の計算式である場合、変換には は含まれませんZero。分岐の 1 つが構文的に計算式ではない場合、または変換された式が含まれていない場合Zero

ケースを見ていきます。

ifとはどちらelseも構文的には計算式です

identity {
    if true then return 1 else return 2
    return 1
}

に変換:

identity.Combine(
    if true then identity.Return(1) else identity.Return(2), 
    identity.Return(1)
)

ブランチがありません

identity {
    if true then return 1
    return 1
}

に変換:

identity.Combine(
    if true then identity.Return(1) else identity.Zero(), 
    identity.Return(1)
)

両方の分岐が指定されていますが、構文的に計算式ではありません

identity {
    if true then printf "Hello World" else ()
    return 1
}

に変換:

identity.Combine(
    if true then printf "Hello World" else (); identity.Zero(), 
    identity.Return(1)
)

最後のケースは、ifステートメントが有効なモナド値を返しても変換が行われるため、やや興味深いものですZero。最後のケースは、その部分が構文的に計算式ではない場合に、ifなしのにも適用されます。elsethen

編集:最近、もう少し調査を行ったところ、元の答えが間違っていることがわかりました。

于 2014-12-17T19:03:56.467 に答える