Reputation: 10204
I read the definition of a State Monad as follows, which includes a definition of flatMap. The literal definition of flatMap is clear to me, but what would be a typical use case of it?
trait State[S,A]{
def run (initial:S):(S,A)
def flatMap[B] (f:A=>State[S,B]):State[S,B] =
State{ s =>
val (s1, a) = run(s)
f(a).run(s1)
}
}
object State{
def apply[S,A](f:S => (S,A)):State[S,A] =
new State[S,A] {
def run(initial:S): (S,A) = f(initial)
}
}
Upvotes: 2
Views: 393
Reputation: 9284
This quote is taken from wikibooks about state monad in haskell.
If you have programmed in any other language before, you likely wrote some functions that "kept state". For those new to the concept, a state is one or more variables that are required to perform some computation but are not among the arguments of the relevant function. Object-oriented languages like C++ make extensive use of state variables (in the form of member variables inside classes and objects). Procedural languages like C on the other hand typically use global variables declared outside the current scope to keep track of state.
In Haskell, however, such techniques are not as straightforward to apply. Doing so will require mutable variables which would mean that functions will have hidden dependencies, which is at odds with Haskell's functional purity. Fortunately, often it is possible to keep track of state in a functionally pure way. We do so by passing the state information from one function to the next, thus making the hidden dependencies explicit.
Basically its purpose is the to write purely functional programs that manipulate state, having the API compute the next state rather than actually mutate anything.
The most common examples for the state monad are:
You can also check the cats page for the state monad
Note: There is an additional more complexed state monad which is called IndexedState monad, which basically gives you the option to change the state.
Upvotes: 2
Reputation: 48410
According to cats State
monad documentation
The
flatMap
method onState[S, A]
lets you use the result of oneState
in a subsequentState
It means we can have state transitions nicely lined up within a for-comprehension like so
val createRobot: State[Seed, Robot] =
for {
id <- nextLong
sentient <- nextBoolean
isCatherine <- nextBoolean
name = if (isCatherine) "Catherine" else "Carlos"
isReplicant <- nextBoolean
model = if (isReplicant) "replicant" else "borg"
} yield Robot(id, sentient, name, model)
In general, purpose of flatMap
is chaining of monadic computations, so whatever monad we have we can stick it within a for-comprehension.
Upvotes: 3