My question is about the sequence
function in Prelude
, the signature of which is as follows:
sequence :: Monad m => [m a] -> m [a]
I understand how this function works for List
of Maybe
s. For example, applying sequence
on [Just 3, Just 9]
gives Just [3, 9]
.
I noticed that applying sequence
on List
of List
s gives its Cartesian Product. Can someone please help me understand how/why this happens?
sequence turns a list of optional values into an optional list.
This works because using lists as monads in Haskell makes them model indeterminism. Consider:
sequence [[1,2],[3,4]]
By definition this is the same as:
do x <- [1,2]
y <- [3,4]
return [x,y]
Just read it as "First a choice between 1 and 2, then a choice between 3 and 4". The list monad will now accumulate all possible outcomes - hence the answer [[1,3],[1,4],[2,3],[2,4]]
.
(for an even more obfuscated example, see here)
sequence
acts as if it were defined like this.
sequence [] = return []
sequence (m:ms) = do
x <- m
xs <- sequence ms
return (x:xs)
(Or sequence = foldr (liftM2 (:)) (return [])
but anyhow…)
Just think about what happens when applied to a list of lists.
sequence [] = [[]]
sequence (list : lists) =
[ x : xs
| x <- list
, xs <- sequence lists
]
Just to explain, why the application of sequence to a list of lists is so different from the application of sequence to a list of Maybe-values:
When you apply sequence
to a list of lists, then the type of sequence is specialized from
sequence :: Monad m => [m a] -> m [a]
to (with the type constructor m set to [])
sequence :: [[] a] -> [] [a]
(which is the same as sequence :: [[a]] -> [[a]]
)
internally, sequence uses (>>=) -- i.e. the monadic bind function. For lists this bind function is implemented completly different than for m set to Maybe!
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