Reputation: 41919
Given:
Prelude>[ [Just 10, Just 20], [Just 5] ]
[ [Just 10, Just 20], [Just 5] ]
it has type:
Prelude> :t [ [Just 10, Just 20], [Just 5] ]
[ [Just 10, Just 20], [Just 5] ] :: Num a => [[Maybe a]]
I'd like to apply this to sequence
:
Prelude> :t sequence
sequence :: Monad m => [m a] -> m [a]
The Monad m
in the above List is: [a]
, as I understand, so I'd expect the types to line up as:
sequence :: Monad m => [m a] -> m [a]
[[a]] -> [[a]]
Assuming that's right, then please help me understand the output:
Prelude> sequence [ [Just 10, Just 20], [Just 5] ]
[[Just 10,Just 5],[Just 20,Just 5]]
Upvotes: 0
Views: 75
Reputation: 54068
It might be easier to do this with just Int
s instead of Maybe Int
s:
> sequence [[10, 20], [5]]
[[10,5],[20,5]]
it :: [[Int]]
The type signature you deduced is correct, it does have type [[a]] -> [[a]]
in this situation, where a ~ Int
in my example or a ~ Maybe Int
in your example. Whenever using sequence
in the list monad, I like to think of it as an N-dimensional Cartesian product. It desugars to something like
sequence [a, b, c] = do
x <- a
y <- b
z <- c
return [x, y, z]
But with an arbitrary number of elements, not just 3. Some other examples might help explain:
sequence [["a1", "a2", "a3"], ["b1", "b2"], ["c1", "c2", "c3"]]
[
["a1","b1","c1"],["a1","b1","c2"],["a1","b1","c3"],["a1","b2","c1"],["a1","b2","c2"],["a1","b2","c3"],
["a2","b1","c1"],["a2","b1","c2"],["a2","b1","c3"],["a2","b2","c1"],["a2","b2","c2"],["a2","b2","c3"],
["a3","b1","c1"],["a3","b1","c2"],["a3","b1","c3"],["a3","b2","c1"],["a3","b2","c2"],["a3","b2","c3"]
]
If you study this output closely, you'll see that we have each element of the a
s matched with each element of the b
s and each element from the c
s. Since there are 3 a
s, 2 b
s, and 3 c
s, there are 3*2*3 == 18
elements in the output.
Upvotes: 3
Reputation: 62848
What sequence
does is to turn something like
[foo, bar, baz]
into something like
do
x <- foo
y <- bar
z <- baz
return [x, y, z]
In your case, we have
do
x <- [Just 10, Just 5]
y <- [Just 5]
return [x, y]
which is the same as
foreach x in [Just 10, Just 5]
foreach y in [Just 5]
return [x, y]
in psuedo-OO syntax.
It should now be fairly obvious why you get the result you do.
Upvotes: 3