나는 모나드를 이해하려고 노력하고 있습니다. 나는 분명히 인정해야합니다. 계산식을 작성하고 많은 수의 인쇄 문을 추가 했으므로 누가 호출되는지를 추적 할 수 있습니다.상태 모나드는 바깥 문맥에 어떻게 묶여 있습니까
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
상기 코드는 다음과 같은 출력
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>
I이 출력의 제 5 줄 이해를 출력한다. 분명히 run
전화는 move
이고 turn
전화는 Get
입니다. 그리고 Bind
을 호출하는 let! pos1 = ...
가 있습니다. 여태까지는 그런대로 잘됐다. 그러나 Bind
에 대한 추가 호출이 있습니다. 그들은 어떻게 생겨나나요? 필자는 피상적 인 수준에서 그러한 외부 상황에 대한 바인딩이 어떻게 든 국가 모나드의 마법이어야한다는 것을 이해하지만이 메커니즘은 어떻게 작동합니까? 그리고 turn
에 또 다른 let! pos2 = ...
이 있는데이 또한 Bind
을 트리거하지만 이번에는 이전에 비해 3 회만 한 번 없습니다!
참여 마술, 모든 연기와 거울이 없다 당신의 explainations
생성 된 desugared 코드를 반사경 또는 ILSpy에서 확인해보십시오. – scrwtp
실제로 기술적 인 측면에 대한 질문은 많지 않습니다. 언어 수준에서 그 외부 범위에 액세스하는 방법은 무엇입니까? – robkuz
'<@ state {...} @>를 검토하는 것이 도움이 될 수 있습니다. '당신이 불분명 한 경우에 평가합니다. 추가 정보가 어떤 도움이되는지는 분명하지 않습니다. – kvb