Reputation: 107
I found some question here: Redefining monad list instance. I'm currently trying to get my head wrapped around monads. But I need some help here, I don't get the instance-definition of lists as monads.
This is my given definition of a list-instance for a monad:
instance Monad [] where
xs >>= f = concat $ map f xs
return x = [x]
fail _ = []
I dont understand, why I need concat in the bind-function.
This is my definition of (>>=)
:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
So I have some monadic value m a
and a function, taking a value a
and producing a monadic value m b
given as parameters. I 'feed' a
from m a
into the function (a -> m b)
and thus get a monadic value m b
as a result.
In my own words: The bind-operator (>>=)
allows to chain monadic functions (returning monadic values) where the value of the output of the earlier function is the input for the next function. Right?
Back to the list-instance. map f xs
uses the function f
on every value in xs
. So map (*2) [1,2,3]
results in [2,4,6]
. And that's all I wanted here or not? How should I use concat
here?
The definition of concat
is as follows:
concat :: [[a]] -> [a]
Why do I get a list of lists in the (>>=)
-function? Is it because list is the monad and I take every single value from that list to feed it to f
and map
just gets singleton-inputs? But how do I iterate over the whole list then? Where does the 'picking each value' happen? And if map
takes the whole list xs as input (that's how I understand it) why should I get a list of lists?
Upvotes: 2
Views: 2319
Reputation: 116139
If
x :: [a]
f :: a -> [b]
then
map f :: [a] -> [[b]]
map f x :: [[b]]
so, we need to flatten the latter into [b]
. This is done by concat
.
Note how f
was already producing a list, so map
makes that into a list-of-lists. This is crucial: if f
was not producing a list but were f :: a->b
, then we don't need concat
-- we don't even need a monad, since a functor providing fmap=map :: (a->b) -> [a] -> [b]
would be enough.
The added benefit of a monad over a functor mainly lies in letting f
produce a value in a monadic type.
Upvotes: 9