How the state monad is linked in an external context

I am trying to understand the state monad, and I can confuse, I must admit. I created Computational Expression and added many print statements, so I can keep track of who will be called when.

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

The above code prints the following output

100 run::
100 move::
100 turn::
100 Get
100 Bind:: <fun:Get@301> <fun:turn@312>
100 Bind:: <fun:Bind@292-2> <fun:move@322>
100 Bind:: <fun:Bind@292-2> <fun:run@329>
200 Bind:: <fun:Bind@292-2> <fun:run@329>
200 Bind:: <fun:Bind@292-2> <fun:move@322>
200 Bind:: <fun:Get@301> <fun:turn@312>
200 Get :: (5, 5)
200 turn:: (5, 5)
100 Get
100 Bind:: <fun:Get@301> <fun:turn@314-1>
200 Bind:: <fun:Get@301> <fun:turn@314-1>
200 Get :: (5, 5)
300 turn:: (5, 5)
100 ReturnFrom <fun:Put@304>
200 move:: <null>
100 Return <null>
100 Return <null>

5 . , run move turn Get. let! pos1 = ..., Bind. . Bind. ? , - , ? let! pos2 = ... turn, Bind, 3 , !

+4
1

, .

, , 'st -> State<'st, 'a>. , run, , - , , , "parent" move turn. , - - .

, , , , , , , , /( ). , , .

- :

type State<'st, 'a> = State of ('st ->'a * 'st),

. . .

, - do! move(), let! x = turn() let! pos1 = state.Get() - , . , , , .

, :

{| let! pattern = expr in cexpr |} => builder.Bind(expr, (fun pattern -> {| cexpr |}))

, expr, Bind , , cexpr. " " expr - Get() - , - cexpr.

, , , let result = p state Bind, .

+4

Source: https://habr.com/ru/post/1666993/


All Articles