haskell执行"zip"奇怪的错误

MYV*_*MYV 7 haskell list empty-list

我在haskell中有以下zip函数的实现

myzip (a:b) (z:g)
    | b == [] = []
    | g == [] = []
    | otherwise = (a,z) : myzip b g
Run Code Online (Sandbox Code Playgroud)

当我将其加载到ghci时,我收到以下错误

No instance for (Eq b)
  arising from a use of `=='
In the expression: g == []
In a stmt of a pattern guard for
               an equation for `myzip':
  g == []
In an equation for `myzip':
    myzip (a : b) (z : g)
      | b == [] = []
      | g == [] = []
      | otherwise = (a, z) : myzip b g
Run Code Online (Sandbox Code Playgroud)

失败,模块加载:无.

我真的不确定为什么这不起作用.任何人都可以给我任何帮助吗?

Ben*_*Ben 14

实际上,你在问题中给出的函数编译得很好.如果你有的话,你得到你引用的错误:

myzip :: [a] -> [b] -> [(a, b)]
myzip (a:b) (z:g)
    | b == [] = []
    | g == [] = []
    | otherwise = (a, z) : myzip b g
Run Code Online (Sandbox Code Playgroud)

使用显式类型签名,说明myzip适用于任何类型a和列表b.但是,你已经使用b == []g == [].等于运算符不是在任何类型上定义的,仅在类型类的成员类型上定义Eq,因此您编写的代码与您提供的类型不匹配.

这就是错误信息非常简单的说法,但是如果你刚刚学习并且尚未开始输入类,那么它有点不清楚.

如果您更改类型签名myzip以表示a并且b需要成为Eq类型类的成员,那么您提供的代码将起作用:

myzip :: (Eq a, Eq b) => [a] -> [b] -> [(a, b)]
Run Code Online (Sandbox Code Playgroud)

或者,如果您完全不使用类型签名(正如您在问题中所做的那样),GHC实际上会从您使用==运算符的事实中推断出这种类型,并且代码只是按原样编译.

然而,检查列表是否为空可以不使用来完成==操作,所以你可以写myzip,这样它确实对任何类型的工作ab.一种方法是使用该null功能:

myzip :: [a] -> [b] -> [(a, b)]
myzip (a:b) (z:g)
    | null b = []
    | null g = []
    | otherwise = (a, z) : myzip b g
Run Code Online (Sandbox Code Playgroud)

但更常见的方法是简单地使用多个方程来定义myzip,基本案例与模式匹配,[]并且主要案例可以假设列表是非空的:

myzip :: [a] -> [b] -> [(a, b)]
myzip (a:[]) _ = []
myzip _ (z:[]) = []
myzip (a:b) (z:g) = (a, z) : myzip b g
Run Code Online (Sandbox Code Playgroud)

请注意,此样式也明显表明您的实现存在错误.你扔掉了最后一个a或者z,并且没有任何情况下列表完全是空的!

当你的等式说myzip (a:b) (z:g),然后检查bg反对空列表,它实际上是太晚检查错误的事情.你并不需要检查,如果b[],则需要检查是否完整列表是空的.但是你已经假设它不是空的并且将它分解成了a:b.这导致你的代码(a)返回错误的结果,因为它丢弃它应该压缩的最后一对元素,以及(b)当其中一个参数是空列表时产生错误.

列表上的递归通常看起来更像这样:

myzip :: [a] -> [b] -> [(a, b)]
myzip [] _ = []
myzip _ [] = []
myzip (a:b) (z:g) = (a, z) : myzip b g
Run Code Online (Sandbox Code Playgroud)

这行为正确.

  • 谢谢!我张贴了一个帖子,出去买了一些快餐,然后回到了写得很好,经过深思熟虑的回复.互联网是神奇的,上面的人是神奇的.你太神奇了!<3 <3 <3 (5认同)