Scala case class with function parameters

I am 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 a purely functional state, from § 6 FP in Scala . run is a function parameter that takes state and emits a tuple of value and new state.

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

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

It seems that the State 'constructor (i.e. apply ) is used to create a new State object. But what does s mean? Is this an “anonymous” state representing any state authority? If so, how is it different from this ? Or s corresponds to the input parameter run , i.e. s from:

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

And why should I use a constructor to define a function? Note that the last character in the flatMap definition is ) not a } , which closes the apply State constructor.

This scenario is slightly different from the standard.

 case class Person(name: String) 

so I thought I would ask ...

+5
source share
1 answer

Your second assumption is correct, s corresponds to the input parameter of the run function, i.e. s , which represents the 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 for storage inside another type (including some monad).

Here, the function that creates the new initial state s (and the new result A ) is wrapped (see return operation) in the monad state, which is implemented as the class case. We need to define a flatMap operation (see bind ) on the monad.

To make the transfer function as a parameter more understandable, the code can be rewritten as follows:

 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 definition of a monad :

  • State[S, +A] is a type constructor that takes two simple types ( s and covariant A ) and returns the monadic type State
  • State.apply(run: S => (A, S)) function accepts a simple function and returns (enters) the State monadic container, therefore it is a "return" monad operator
  • State.flatMap[B](f: A => State[S, B]): State[S, B] matches the bind operator

The case class is used only to use the explicit function "return" ( apply ) instead of using the new operator.

+10
source

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


All Articles