Scala and State Monad

前端 未结 3 2492
陌清茗
陌清茗 2021-02-20 13:36

I have been trying to understand the State Monad. Not so much how it is used, though that is not always easy to find, either. But every discussion I find of the State Monad ha

3条回答
  •  心在旅途
    2021-02-20 14:14

    To understand the "second run" let's analyse it "backwards".

    The signature def flatMap[B](f: A => State[S, B]): State[S, B] suggests that we need to run a function f and return its result.

    To execute function f we need to give it an A. Where do we get one?
    Well, we have run that can give us A out of S, so we need an S.

    Because of that we do: s => val (a, t) = run(s) .... We read it as "given an S execute the run function which produces us A and a new S. And this is our "first" run.

    Now we have an A and we can execute f. That's what we wanted and f(a) gives us a new State[S, B]. If we do that then we have a function which takes S and returns Stats[S, B]:

    (s: S) => 
       val (a, t) = run(s)
       f(a) //State[S, B]
    

    But function S => State[S, B] isn't what we want to return! We want to return just State[S, B].

    How do we do that? We can wrap this function into State:

    State(s => ... f(a))
    

    But it doesn't work because State takes S => (B, S), not S => State[B, S]. So we need to get (B, S) out of State[B, S].
    We do it by just calling its run method and providing it with the state we just produced on the previous step! And it is our "second" run.

    So as a result we have the following transformation performed by a flatMap:

    s =>                   // when a state is provided
      val (a, t) = run(s)  // produce an `A` and a new state value
      val resState = f(a)  // produce a new `State[S, B]`
      resState.run(t)      // return `(S, B)`
    

    This gives us S => (S, B) and we just wrap it with the State constructor.

    Another way of looking at these "two runs" is:
    first - we transform the state ourselves with "our" run function
    second - we pass that transformed state to the function f and let it do its own transformation.

    So we kind of "chaining" state transformations one after another. And that's exactly what monads do: they provide us with the ability to schedule computation sequentially.

提交回复
热议问题