6

I'm working with this code:

case class State[S, +A](run: S => (A, S)) {
  ...                                          
  def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {    
    val (a, s1) = run(s)
    f(a).run(s1)
  })
  ...                                        
}

This is an abstraction for working with purely functional state, from §6 of FP in Scala. run is function parameter that takes a state and emits a tuple of a value and the new state.

My question is around the syntax s => in this section:

... B] = State(s => { ...

This appears to be using the State 'constructor' (ie apply) to build a new State object. But what does the s represent? Is it an 'anonymous' State, representing any State instance? If so, how is it different from this? Or does s correspond to the input parameter of run ie the S from:

... (run: S => ....  

And why would I be using a constructor for a function definition? Notice that the last symbol of the flatMap definition is a ) not a }, that is closing the State apply constructor.

This scenario is a bit different than the standard

case class Person(name: String)

scenario, so I thought I'd ask...

1 Answer 1

9

Your second assumption is correct, s corresponds to the input parameter of run function, ie the S, which represents an actual state passing through the chain. So s => {...} is just a lambda definition of type S => (A, S). Lambdas and functions in Scala are first-class citizens (values), so you can pass them as parameters to hold inside some another type (including some monad).

Here the function, which produces new raw state S (and new result A), is wrapped (see return operation) to the monad State, which is implemented as case class. We need it to define flatMap operation (see bind) over the monad.

To make it more clear about the passing function as parameter, the code may be rewritten to:

case class State[S, +A](run: S => (A, S)) {
    def flatMap[B](f: A => State[S, B]): State[S, B] = {
        def newState(s: S) = {    
           val (a, s1) = run(s)
           f(a).run(s1)
        }
        State(newState _)
    }
}

So, according to the monad definition:

  • State[S, +A] is a type constructor which takes two plain types (S and covariant A) and returns monadic type State
  • State.apply(run: S => (A, S)) function takes a plain function and returns (lifts into) monadic container State, so it is a "return" operator of the monad
  • State.flatMap[B](f: A => State[S, B]): State[S, B] is corresponding to the "bind" operator

Case class is used just to have explicit "return" function (apply) instead of using new operator.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks very much @dk14. It's late here so I'll grok this properly tomorrow and vote. Interestingly I'm watching Scalaz State Monad which shows this exact situation. Paraphrasing the presenter at 18:40, the syntax is a "lambda that takes an S and returns an SB, lifted into State".
In the example from your question such lifting from plain type to the monad ("return" operator) is represented by State.apply(run: S => (A, S)). By the way, it's an 2012 year video, modern scalaz doesn't accept the S => (A, S) inside State.apply - it's doing it only in States.state(f: S => (S, A)) method, so there is an only one "return" method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.