Can someone show a simple example where state monad can be better than passing state directly?
bar1 (Foo x) = Foo (x + 1)
vs
bar2 :: State Foo Foo
bar2 = do
modify (\(Foo x) -> Foo (x + 1))
get
Can someone show a simple example where state monad can be better than passing state directly?
vs
|
||||
State passing is often tedious, error-prone, and hinders refactoring. For example, try labeling a binary tree or rose tree in postorder:
Here I had to manually label states in the right order, pass the correct states along, and had to make sure that both the labels and child nodes are in the right order in the result (note that naive use of Also, if I try to change the code to preorder, I have to make changes that are easy to get wrong:
Examples:
Contrast the state monad solution:
Not only is this code more succinct and easier to write correctly, the logic that results in pre- or postorder labeling is far more transparent. PS: bonus applicative style:
|
|||||||||||||
|
As an example to my comment above, you can write code using the
Note that using additional operators from
which is another benefit of using
At this point it isn't too bad, but once we get to the next step I think you'll see where the code duplication really comes in:
Another benefit of wrapping this up in a
Which allows for much more flexibility when processing values calculated at runtime compared to static values. The difference between manual state passing and using the
These will now work with |
||||
|
In my experience, the point of many Monads doesn't really click until you get into larger examples, so here is an example use of The pattern is that this web service can be called with a bunch of options of different types, though all except for one of the options have decent defaults. If I get a incoming JSON request with an unknown key value, I should abort with an appropriate message. I use the state to keep track of what the current config is, and what the remainder of the JSON request is, along with a bunch of accessor methods. (Based on code currently in production, with the names of everything changed and the details of what this service actually does obscured)
|
|||
|
State
monad. Think of the latter as a design pattern. You can also combineState
with other monads easily. – Jubobs Jul 17 '15 at 12:46State
is probably overkill. Do you have a specific, real-life example? – Jubobs Jul 17 '15 at 13:16State
type is simply a wrapper around argument passing with a tuple returned. The purpose of using it is to have a better defined set of functions, where you basically say "All of these functions are designed to work together", and to reduce the amount of typing you need to do. You can do everything thatState
can using just argument passing, butdo
notation makes the argument passing transparent. This aids the readability of your code, makes it more composable, and reduces how much you actually have to write to achieve the same goal. – bheklilr Jul 17 '15 at 13:25State
monad is just a design pattern like a class in OOP, making it easier to reuse code in particular contexts. – bheklilr Jul 17 '15 at 13:25