【问题标题】:haskell implementation of "zip" strange error“zip”的haskell实现奇怪的错误
【发布时间】:2013-05-05 04:17:02
【问题描述】:

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

myzip (a:b) (z:g)
    | b == [] = []
    | g == [] = []
    | otherwise = (a,z) : myzip b g

当我将它加载到 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

失败,已加载模块:无。

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

【问题讨论】:

    标签: list haskell empty-list


    【解决方案1】:

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

    myzip :: [a] -> [b] -> [(a, b)]
    myzip (a:b) (z:g)
        | b == [] = []
        | g == [] = []
        | otherwise = (a, z) : myzip b g
    

    有一个明确的类型签名表明myzip 适用于任何 类型ab 的列表。但是您使用过b == []g == []。等式运算符没有在任何类型上定义,仅在属于Eq 类型类成员的类型上定义,因此您编写的代码与您提供的类型不匹配。

    这就是错误消息直截了当地说的内容,但如果您只是在学习并且还没有开始输入类,那么它有点不清楚。

    如果您将myzip 的类型签名更改为说ab 需要是Eq 类型类的成员,那么您提供的代码将起作用:

    myzip :: (Eq a, Eq b) => [a] -> [b] -> [(a, b)]
    

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

    但是,检查列表是否为空可以不使用== 运算符来完成,因此您可以编写myzip,以便它确实可以对任何类型ab 进行操作。一种方法是使用null 函数:

    myzip :: [a] -> [b] -> [(a, b)]
    myzip (a:b) (z:g)
        | null b = []
        | null g = []
        | otherwise = (a, z) : myzip b g
    

    但更常见的方法是简单地使用多个方程式来定义 myzip,基本情况与模式 [] 匹配,而主要情况则假设列表非空:

    myzip :: [a] -> [b] -> [(a, b)]
    myzip (a:[]) _ = []
    myzip _ (z:[]) = []
    myzip (a:b) (z:g) = (a, z) : myzip b g
    

    请注意,这种风格也表明您的实现中存在错误。您正在丢弃最后一个 az,并且列表完全为空时没有任何情况!

    当您的等式显示 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
    

    这行为正确。

    【讨论】:

    • 谢谢!我张贴了一个帖子,出去买了一些快餐,然后又回到了一个写得很好的和经过深思熟虑的回复。互联网很神奇,上面的人也很神奇。你很神奇!
    猜你喜欢
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 2011-01-08
    • 2016-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多