3 ms·
>This seems too simple. There is a reason people say monads are simple. The comment you are replying to is describing the concrete example of the List monad.
by gizmo686 10y ago
>This seems too simple.
There is a reason people say monads are simple.
The comment you are replying to is describing the concrete example of the List monad. To answer you direct questions, it is probably better to look at another example: the State monad.
The idea behind state is simple. Suppose you have a bunch of functions that you want to call in sequence. This is a simple enough problem; just do f(g(h(x))) or `h(x) |> g |> f` [0].
Now, suppose that, in addition to piping a value from one function to the next, we want to keep track of additional state. For example, maybe we want to use a psuedo-random number generator in some of the functions and have to keep track of its internal state. One way to do that would be to simply modify each function so that the returned value includes the state; but this quickly becomes unwieldy. The State monad provides a way to automatically thread the state through the functions. So we can do:
put initSeed >>= h >>= (get \currentSeed -> g currentSeed) >>= (get \nextSeed -> f nextSeed)
or (with a bit of syntactic sugar:
put initSeed
h
currentSeed <- get
g currentSeed
nextSeed <- get
f nextSeed
in this example g and f would be expected to call put to update the internal state.
Now, suppose you want to keep applying a function until some condition becomes true about the state. In this case, it makes sense to talk about a while loop:
while (get >>= \state -> state =/= 7) f
The above snippet will repeatadly bind f until the internal state is 7.
It turns out, that we can implement while in terms of only the Monad interface:
while condition action = do
x <- condition
if x then (action >> (while condition action))
else return ()
It turns out that most control structures can be encoded into monads in this way.
The IO system is a bit hacky. The idea is that the universe is a big state machine. So, when we do `println "Hello World"`, we are not causing a side effect, we are just updating our internal state to say that we printed "Hello World". Simmilarly, getLine just peaks into our internal state to see what the input at the current time has always been. Of course, for some reason, GHC does not give us the full get or put functions for the IO monad; but they could exist in theory, and that is enough to pretend that side effects do not exist.
[0] Not actual haskell because we can't agree on a name for the pipeline operator I am calling "|>" here.