Haskell/Understanding monads/Solutions/IO
Print a list of arbitrary values
[edit | edit source]The function map
would print out every value from the list, but would produce [IO ()]
. We'd thus need to chain sequence $ map
, which is exactly how the function mapM
is defined. Because we are not collecting the results of print
but focus only on its actions, we can discard them with mapM_
.
printList :: Show a => [a] -> IO ()
printList = mapM_ print
Generalize the bunny invasion example
[edit | edit source]If we were not working with monads, applying function f :: a -> a
three times would be achieved by f(f(f(x)))
, which can be rewritten as (f . f . f) x
. This suggests that if we want to generalize it to apply the function n
times we could fold the list of f
s using the (.)
as the accumulating function:
composeTimes :: Int -> (a -> a) -> (a -> a)
composeTimes n f = foldr (.) id $ replicate n f
The initial value for foldr
is id
since .
Now all we have to do is translate this to monads, that is replace (.)
with monad composition operator (>=>)
, id
with return
and arbitrary f
with generation
, yielding:
generations :: Int -> a -> [a]
generations n = foldr (>=>) return $ replicate n generation
We can verify that it works as expected:
Prelude> ["bunny"] >>= generations 0
["bunny"]
Prelude> ["bunny"] >>= generations 1
["bunny","bunny","bunny"]
Prelude> ["bunny"] >>= generations 2
["bunny","bunny","bunny","bunny","bunny","bunny","bunny","bunny","bunny"]
What is the expected behavior of sequence
for the Maybe
monad?
[edit | edit source]The Maybe
monad represents a possible failure. If a failure occurred at any point in computing a list then the whole list cannot be computed, thus we expect that sequence
of a list will produce Nothing
if there are Nothing
s in the list and Just
a list otherwise. This is indeed what happens:
Prelude> sequence [Just 1, Just 2, Just 3]
Just [1,2,3]
Prelude> sequence [Just 1, Nothing, Just 3]
Nothing