The canonical explanation for this is that you want to form a new monadic value out of two existing ones. Let's look at the type of putStr,
IO ()
That means it's some black box, that when executed, will "return" the (one-and-only) value of unit type. The key idea behind monadic computation is that you have a combinator >>=
which will put together two monadic expressions, feeding the result of one into the next (more accurately, a function that creates the next). One critical point is that the IO
library provides this combinator, meaning that,
- It [IO in this case] could skip the second monadic value, for example when the first one throws an exception.
- It can pass other data around, in the case of
IO
a RealWorld
state containing open file handles, etc.
- It can "ensure" that the first one evaluates first, unlike most lambda expression evaluations, where the outermost ("last") terms are expanded first. This is important for print, where the first print needs to change the world first.
In your case, use it like this,
putStr "0" >>= (\c -> putStr "0")
There's a shortcut, of course,
putStr "0" >> putStr "0"
and the do-notation, as mentioned by another poster, which is yet more syntax sugar,
do
putStr "0"
putStr "0"
case input of 0 -> … 1 -> …
– Touchdown