私は状態モナドを理解しようとしています。私は認めなければならないと大変混乱しています。 私は計算式を作成し、多くの印刷ステートメントを追加したので、いつ誰が呼び出されるかをフォローアップすることができます。状態モナドは外部コンテキストにどのようにバインドするのですか
type State<'st,'a> =
| Ok of 'a * 'st
| Error of string
and StateMonadBuilder() =
member b.Return(x) = printfn "100 Return %A" x; fun s -> Ok (x, s)
member b.ReturnFrom(x) = printfn "100 ReturnFrom %A" x; x
member b.Bind(p, rest) =
printfn "100 Bind:: %A %A" p rest
fun state ->
printfn "200 Bind:: %A %A" p rest
let result = p state in
match result with
| Ok (value,state2) -> (rest value) state2
| Error msg -> Error msg
member b.Get() =
printfn "100 Get"
fun state ->
printfn "200 Get :: %A" state
Ok (state, state)
member b.Put s = fun state -> Ok ((), s)
let state = StateMonadBuilder()
let turn() =
state {
printfn "100 turn::"
let! pos1 = state.Get()
printfn "200 turn:: %A" pos1
let! pos2 = state.Get()
printfn "300 turn:: %A" pos1
return! state.Put(fst pos1, snd pos1 - 1)
}
let move() =
state {
printfn "100 move::"
let! x = turn()
printfn "200 move:: %A" x
let! y = turn()
printfn "200 move:: %A" y
return x
}
let run() =
state {
printfn "100 run::"
do! move()
}
run() (5,5) |> ignore
上記のコードは、私は、この出力の最初の5行を理解する次の出力
100 run::
100 move::
100 turn::
100 Get
100 Bind:: <fun:[email protected]> <fun:[email protected]>
100 Bind:: <fun:[email protected]> <fun:[email protected]>
100 Bind:: <fun:[email protected]> <fun:[email protected]>
200 Bind:: <fun:[email protected]> <fun:[email protected]>
200 Bind:: <fun:[email protected]> <fun:[email protected]>
200 Bind:: <fun:[email protected]> <fun:[email protected]>
200 Get :: (5, 5)
200 turn:: (5, 5)
100 Get
100 Bind:: <fun:[email protected]> <fun:[email protected]>
200 Bind:: <fun:[email protected]> <fun:[email protected]>
200 Get :: (5, 5)
300 turn:: (5, 5)
100 ReturnFrom <fun:[email protected]>
200 move:: <null>
100 Return <null>
100 Return <null>
を印刷します。明らかにrun
はと、turn
はGet
となります。 そしてBind
への呼び出しをトリガーするlet! pos1 = ...
があります。ここまでは順調ですね。しかし、Bind
への追加の呼び出しがあります。 彼らはどのようにして生まれますか? 私は表面的なレベルで、これらの外部コンテキストへのバインディングは何とか国家モナドの魔法でなければならないと理解しますが、このメカニズムはどのように機能しますか? そして、turn
のにもう1つのlet! pos2 = ...
がありますが、これは前回と同じように3回だけではありません。
関与魔法、すべての煙と鏡はありませんあなたのexplainations
生成されたdesugaredコードを反射板またはILSpyで見てみてください。 – scrwtp
実際には、その技術的側面についてはそれほど疑問ではありません - さらに、言語レベルでこれらの外部スコープにアクセスすることも可能です – robkuz
'<@ state {...} @>あなたが不明確な場合に評価します。どのような追加情報が役立つかは私には分かりません。 – kvb