编译时输入错误

时间:2012-02-17 22:52:52

标签: haskell

我不明白为什么以下代码无法编译:

 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)

它会产生以下错误:

pr27.hs:13:20:
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] -> [a]
Actual type: [a] -> [[a]]
In the return type of a call of `traverse'
In the first argument of `map', namely `(traverse x)'
Failed, modules loaded: none

但是当我只加载traverse并在类似于上面的表达式中使用它时,我得到了所需的结果。发生了什么事?

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]]]

1 个答案:

答案 0 :(得分:4)

问题是comb必须返回[[a]]类型的值。 traverse返回类型[[a]]的值,因此将其映射到另一个列表会产生[[[a]]],其嵌套级别太高。

让我们看看map。它的类型为map :: (x -> y) -> [x] -> [y]traverse x的类型为[a] -> [[a]]。现在我们需要将两者结合起来。为此,我们将x替换为[a],将y替换为[[a]],获取([a] -> [[a]]) -> [[a]] -> [[[a]]]。这清楚地表明映射traverse的结果必须至少有三个嵌套级别。

如果你看一下你的例子,这就是你实际得到的。对于comb,您只需要两个级别。

你的例子在GHCi中工作的原因是因为一个表达式可以有任何类型。您的map (traverse 3) [[1,2], [2,1]]表达完全合法;但是,它具有类型Num a => [[[a]]],它是一系列数字列表。 (试试看::t map (traverse 3) [[1,2], [2,3]]。)但是,comb的类型为[a] -> [[a]]。这意味着结果必须是列表列表,而不是列表列表。所以问题是map (traverse 3)comb不兼容,而不是它本身就是非法的。