Rewrite haskell list comprehension in do-notation
do-notation, haskell, list-comprehension
Solution
Look closely at the error message:
Couldn't match type `a' with [a]
`a' is a rigid type variable bound by
the type signature for d :: [[a]] -> [[a]]
Expected type: [[a]]
Actual type: [a]
In the second argument of `(:)', namely `b'
In a stmt of a 'do' block: return a : b
This means that it was parsed as
(return a) : b
and thus `b` became the second argument to `(:)` there; but you intended it as
return (a : b)
Problem
I have read in Learn you a Haskell, that list comprehensions in Haskell could be rewritten as monadic joins or (which is practically the same) do-notation. However, when I try to rewrite the following code (produce all possible lists having each element from one of given lists): ``` c :: [[a]] -> [[a]] c [] = [[]] c (x:xs) = [a:b | a <- x, b <- c xs] ``` in such a manner: ``` d :: [[a]] -> [[a]] d [] = [[]] d (x:xs) = do a <- x b <- d xs return a:b ``` I get the following error: ``` Couldn't match type `a' with [a] `a' is a rigid type variable bound by the type signature for d :: [[a]] -> [[a]] Expected type: [[a]] Actual type: [a] In the second argument of `(:)', namely `b' In a stmt of a 'do' block: return a : b ``` if I change the last line of `do` to this: `return a:[b]`, I don't get errors, but the result is obviously incorrect: ``` ghci> c [[1, 2], [3, 4]] [[1,3],[1,4],[2,3],[2,4]] ghci> d [[1, 2], [3, 4]] [[1],[3],[1],[],[1],[4],[1],[],[2],[3],[2],[],[2],[4],[2],[]] ``` So the questions are: - How can I rewrite this list comprehension? - Are list comprehension and do-notation interchangeable, how replacement can be done generically?