Haskell/Understanding monads/Solutions/IO

From Wikibooks, open books for an open world
Jump to navigation Jump to search

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 fs 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 Nothings 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