Now that I'm comfortable with the simpler monads like Maybe and List, I challenged myself to redo a small coding challenge I saw a few month ago using haskell and the State monad.
I went for http://www.serpentine.com/wreq/tutorial.html to make http requests. It's a simple and complete library. The other important dependency is the mtl to get the State monad.
The star of the post. In Haskell, functions are pure which means they don't have side effects and their output is only a function of their input (no access to outside state/variables).
Of course, sometimes, carrying a state between computation is required. Although this information could be embedded as an additional parameter, it quickly become cumbersome, and it makes composition of functions more difficult.
As usual in Haskell, monads provide an elegant solution to this problem.
get is provided by the State monad, and allow one to retrieve the internal state. compute here is just a pure function (which needs to have type String -> (a, String)). put set the internal state and return set the result of the computation.
let (result, nextState) = runState initialState "foo"
In my case, the function to compute the next state involve making an http request, and this is impure. That's where monad transformers come into play. They allow one monad to be executed in the context of another monad. In my case, I had to use StateT s IO a which means a function with the signature s -> IO (a, s). This special monad can transform its state.
Note the liftIO here, which means the given action has to be executed in the IO context. This is valid here because the transformer is IO.
runStateT is the equivalent of runState and allow to retrieve the result and the new state from the compution embedded inside the monad. Then, depending on the new state (is there more stuff to fetch?), I'm either done or I recurse with the new updated state.
This was an interesting exercise, although I'm pretty sure it would be easier to just pass the state as function argument here. This was also a neat opportunity to do network requests, as a web dev, it's my bread and butter and it feels more practical than most abstract exercises from books I've read.
This post also uses the StateT monad (combined with the list monad) in a very clever way, and is well worth the read.