我正在学习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)
我期待你的回应
答案 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