suk*_*mel 6 haskell list-comprehension do-notation
我读过" 了解你一个Haskell",Haskell中的列表理解可以改写为monadic join或(实际上是相同的)do-notation.
但是,当我尝试重写以下代码时(生成所有可能的列表,其中包含给定列表中的每个元素):
c :: [[a]] -> [[a]]
c [] = [[]]
c (x:xs) = [a:b | a <- x, b <- c xs]
Run Code Online (Sandbox Code Playgroud)
以这种方式:
d :: [[a]] -> [[a]]
d [] = [[]]
d (x:xs) = do
a <- x
b <- d xs
return a:b
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
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
Run Code Online (Sandbox Code Playgroud)
如果我改变了最后一行do:return a:[b]我没有得到错误,但结果显然不正确:
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],[]]
Run Code Online (Sandbox Code Playgroud)
所以问题是:
Wil*_*ess 10
仔细查看错误消息:
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
这意味着它被解析为
(return a) : b
Run Code Online (Sandbox Code Playgroud)
从而b成为(:)那里的第二个论点; 但你打算这样做
return (a : b)
Run Code Online (Sandbox Code Playgroud)