[英]another type error
Why doesn't this compile? 为什么不编译?
append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xs
traverse :: a -> [[a]] -> [[a]]
traverse x [[]] = [[x]]
traverse x [(y:ys)] = append [(x:y:ys)] (map (y:) (traverse x [ys]))
comb :: [a] -> [[a]]
comb [] = [[]]
comb (x:[]) = [[x]]
comb (x:y:[]) = [[x,y],[y,x]]
comb (x:xs) = map (traverse x) (comb xs)
It fails with this error: 失败并显示以下错误:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for comb :: [a] -> [[a]] at pr27.hs:10:1
Expected type: [[a]]
Actual type: [a]
In the first argument of `comb', namely `xs'
In the second argument of `map', namely `(comb xs)'
xs is a tail of list and so it is a valid argument for comb?? xs是列表的尾部,因此它是comb的有效参数? Thanks , David Kramf 谢谢大卫·克拉姆夫
Your method comb xs
returns a type [[a]]
. 您的方法comb xs
返回类型[[a]]
。 When passed into map (traverse x)
, this calls traverse x
with each element of [[a]]
, ie elements of type [a]
. 当传递到map (traverse x)
, traverse x
使用[[a]]
每个元素(即[a]
类型的元素map (traverse x)
调用traverse x
。 However, traverse x
has the type [[a]] -> [[a]]
, so the mismatch here is traverse
is expecting a [[a]]
but you're giving it a [a]
. 但是, traverse x
的类型为[[a]] -> [[a]]
,因此此处的traverse
不匹配是traverse
[[a]]
期望值,但您给了它[a]
。
Some pointers: 一些指针:
++
尽管可能具有教育意义,但您不需要自己的附加函数-您可以使用++
comb
-- do you really need more than comb []
and comb (x:xs)
? 您可能拥有的comb
数量比comb []
需要的要多-您真的需要的不仅仅是comb []
和comb (x:xs)
吗? traverse
will not match a second argument containing more than one list 如所写, traverse
将不匹配包含多个列表的第二个参数 I have not run this through Haskell myself, but I think that last point may be your main problem. 我自己还没有通过Haskell来解决这个问题,但是我认为最后一点可能是您的主要问题。
Edit: @Kevin Ballard's answer is of course correct with respect to why you get the particular type error. 编辑:@Kevin Ballard的答案对于您为什么会收到特定类型错误当然是正确的。 But, I believe the larger problem is that, at some point, you will need to concat
-enate (ie, flatten) a list of lists of combinations (actually permutations, if I understand your existing code), and I don't see that here. 但是,我认为,更大的问题是,在某些时候,你需要concat
-enate(即压平)组合的列表的列表(实际上排列,如果我理解你的现有代码),我没有看到在这里。
As the flip side of this coin, perhaps the type signature of traverse should be a -> [a] -> [[a]]
? 作为硬币的反面,也许导线的类型签名应该是a -> [a] -> [[a]]
?
My advice would be to stay concrete. 我的建议是保持具体。 The type variable a can match Int, [ Int ], [[ Int ]] and so on, which can lead to confusion at the early stages of development. 类型变量a可以匹配Int,[Int],[[Int]]等,这可能会导致开发初期的混乱。 Once the program works for concrete types, it is often not very difficult to generalize over arbitrary types. 一旦程序适用于具体类型,通常就很难对任意类型进行概括。
Here is the conrete version of your previous (buggy) program: 这是您以前的(越野车)程序的具体版本:
append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xs
traverse :: Int -> [Int] -> [[Int]]
traverse x [] = [[x]]
traverse x (y:ys) = append [(x:y:ys)] (map (y:) (traverse x ys))
comb :: [Int] -> [[Int]]
comb [] = [[]]
comb (x:[]) = [[x]]
comb (x:y:[]) = [[x,y],[y,x]]
comb (x:xs) = map (traverse x) (comb xs)
ghci would complain about the last line: ghci会抱怨最后一行:
Couldn't match expected type `Int' with actual type `[Int]'
Expected type: [Int] -> [Int]
Actual type: [Int] -> [[Int]]
In the return type of a call of `traverse'
In the first argument of `map', namely `(traverse x)'
which looks more understandable than the one you encountered. 看起来比您遇到的更容易理解。 Whereas [a] can mean anything from [ Int ], [[ Int ]], etc., [ Int ] can mean .. well, [ Int ]. [a]可以表示[Int],[[Int]]等中的任何内容,而[Int]可以表示..好,[Int]。
As you said in your last question, the traverse function is fine: 正如您在上一个问题中所说的那样,遍历功能很好:
Main> map (traverse 3) [[1,2],[2,1]]
[[[3,1,2],[1,3,2],[1,2,3]],[[3,2,1],[2,3,1],[2,1,3]]]
with type: 类型:
Main> :type map (traverse 3) [[1,2],[2,1]]
map (traverse 3) [[1,2],[2,1]] :: [[[Int]]]
Now, recall the type of comb function: 现在,回想一下梳子功能的类型:
comb :: [Int] -> [[Int]]
The reason of the type error should be clear enough. 类型错误的原因应该很清楚。 All you need to do is to "combine" the results of map in the last line, like so: 您需要做的就是在最后一行“组合” map的结果,如下所示:
comb (x:xs) = concat $ map (traverse x) (comb xs)
Here is the output of the (fixed) program: 这是(固定)程序的输出:
Main> comb [1,2,3]
[[1,2,3],[2,1,3],[2,3,1],[1,3,2],[3,1,2],[3,2,1]]
Now you can try generalizing to arbitrary types. 现在,您可以尝试泛化为任意类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.