I was reading about list monads and encountered:
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
it produces
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
Here's how I understand it:
Implicit parentheses are:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
([1,2] >>= \n -> ['a','b'])
should give [('a',1),('b',1),('a',2),('b',2)]
because
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs) -- this line
fail _ = []
so concat (map f xs)
is concat (map (\n -> ['a','b']) [1,2])
which should produce [('a',1),('b',1),('a',2),('b',2)]
- quite the opposite of the actual output.
Then I don't understand >>= (\ch -> return (n,ch))
part - I think that n
here has no sense. That specific reasoning is flawed, could you please explain how that expression([1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
) is computed step-by-step?
Your implicit parentheses are wrong. The way you have it, the n
parameter to the first lambda would not be in scope in the return
. It is more like:
([1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch))))
Which becomes:
concatMap (\n -> concatMap (\ch -> [(n,ch)]) ['a','b']) [1,2]
No, you're using wrong parenthesization. It's nested to the right, so that
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
=
[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch) ))
=
do { n <- [1,2]
; do { ch <- ['a','b']
; return (n,ch) }}
=
for n in [1,2]: -- pseudocode
for ch in ['a','b']:
return (n,ch)
=
[ r | n <- [1,2], ch <- ['a','b'], r <- [(n,ch)] ] -- return == (:[])
=
[ (n,ch) | n <- [1,2], ch <- ['a','b'] ]
=
pure (,) <*> [1,2] <*> ['a','b'] -- using list applicative
=
[(1,'a'), (1,'b'), (2,'a'), (2,'b')]
and the innermost list is "spinning" the fastest, like in a car's odometer.
You are absolutely right, with the wrong parenthesization the n
binding would make no sense. It is precisely for that reason that it must associate to the right, to make the nested binding possible; for the nested computations are the essence of the monad:
[ foo x | x <- xs ] -- functor : amendable computations
[ bar x y | x <- xs AND y <- ys ] -- applicative : combinable computations
[ baz x y | x <- xs, y <- foo x ] -- monad : reinterpretative computations
(and yes, omitting parentheses in learning material is the root of all evil... not really, but still...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With