haskell错误,压缩列表

时间:2014-03-09 14:10:13

标签: list haskell

我正在学习Haskell,我尝试编写一个代码,以某种方式拉开两个列表。我的代码应该在这些输入中返回这些列表

输入:

[1,2,3] [6,5,4] 

[1,2,3] [6,5]

[1,2] [6,5,4]

输出:

[(1,6),(2,5),(3,4)]
[(1,6),(2,5),(3,3)]
[(1,6),(2,5),(4,4)]

我的代码就是这个

zip' :: (Integral i, Integral b) => [i] -> [b] -> [(i,b)]
zip' [][] = []
zip' (x:xs)[] = bmi x : zip' xs []
                where bmi x = (x,x)
zip' [](x:xs) = bmi x : zip' [] xs
                where bmi x = (x,x)
zip' (x:xs) (y:ys) = bmi x y : zip' xs ys
                     where bmi x y = (x,y)     

我期待你的回应

2 个答案:

答案 0 :(得分:9)

问题在于你正在使用具有不同元素类型的两个列表,然后当一个列表用完时尝试使用其他列表元素代替它。这不起作用,因为它们没有相同的类型。

最简单的解决方案就是将类型签名修复为

 zip' :: [a] -> [a] -> [(a, a)]

另一个选项,我之所以提到,因为你最初有Integral个约束,就是尝试在列表的每个元素之间进行转换。

 zip' :: (Integral i, Integral j) => [i] -> [j] -> [(i, j)]

现在你bmi看起来像这样

  ...
   where bmi x = (x, fromIntegral x)
  ...
    where bmi x = (fromIntegral x, x)
  ...
    where bmi x y = (x, y)

答案 1 :(得分:4)

去掉那个bmi并且只是内联元组(这就是编译器将要做的事情),然后更明显的是什么错误:

zip' (x:xs)[]  = (x,x) : zip' xs []

这里有(x,x),显然有同源元组的类型,但(i,b)签名允许不同类型的任意组合。

如果您认为像bmi这样的中间函数以某种方式切换类型转换,那么在Haskell中有从不隐式类型转换! (非常好的理由,你很快就会体会到更多经验)。

必须始终明确表示类型转换。在您确实可行的情况下,使用Integral约束:任何两个Integral类型都可以使用fromIntegral转换为另一个。

zip' (x:xs) []  = (       x       , fromIntegral x ) : zip' xs []
zip' [] (y:ys)  = ( fromIntegral y,        y       ) : zip' [] ys