【问题标题】:Haskell colon within the zip functionzip函数内的Haskell冒号
【发布时间】:2015-08-03 23:16:57
【问题描述】:

我很难理解这个 Haskell 函数。我表面上知道它做了什么,但我不确定它是如何实现这个功能的。

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

我的想法:

  1. zip 是函数的名称。
  2. zip 有 2 个参数。 (我相信咖喱在这里并不重要)。
  3. 参数为(x:xs)(y:ys)
  4. zip 返回元组类型 (x,y) 的列表。

现在对参数不太了解

(x:xs) (y:ys)

冒号在列表的开头附加一些东西(返回列表),那么为什么我们要在要压缩的列表中附加一些东西呢?函数定义中的xy是什么?

右侧看起来很明显:我们将元组 (x,y) 插入 (0) 到 zip 返回的元组列表中。

(x,y) : zip xs ys 

现在zip xs ys = [ ] 如果我们只传递 2 个列表,为什么我们总是想要一个空列表?

您能否解释一下对zip 的以下调用将如何进行评估:

zip [5,7,9] [1,3,5,11]

【问题讨论】:

  • 您要了解左侧:的关键字是“模式匹配”。这是一个递归定义,其中第二个等式(仅在第一个与参数不匹配时使用)是基本情况。与this question and its answers 比较(请注意,基本情况先出现,这也有效)。
  • 谢谢,这也有帮助
  • 澄清你的假设 1. - 4. 都是正确的,如果你对函数的类型有疑问,你可以启动 ghci 并输入 Prelude>:t zip 来了解它的类型,这适用于任何函数,只要它在范围内,所以如果你有一个不在Prelude 中的函数说splitOn 你必须做Prelude> import Data.List.Split(这就是 splitOn 的来源)为了让它在范围内.对于运算符,您必须将它们包装在括号中 Prelude> :t (/=).
  • @JonasShinaniganz 如果您发现其中一个完整且准确,请记住接受答案。好问题!

标签: haskell


【解决方案1】:

方程左侧的(x:xs) 是一个模式。它解构一个论点。

等式右侧的(x:xs) 是一个表达式。它构造一个值。

zip (x:xs) (y:ys) = 

意思是,zip 是一个函数,需要两个参数,都应该是非空列表。

                      (x,y) : zip xs ys 

这构造了一个输出值;它的头部是(x,y),尾部是调用zip xs ys的结果:

       [ x1,   x2, x3, x4, ....
       [ y1,   y2, y3, y4, ....
      --------------------------
    [ (x1,y1) , ................

尝试调用zip (5,7,9) (1,3,5,11) 将不起作用(会导致编译时类型不匹配错误),因为这里的第一个参数是三元组,第二个是四元组;这些是不是列表。列表具有不同的大小,但元组具有固定的大小。因此正确的调用是zip [5,7,9] [1,3,5,11]。通过将数字替换为上述方案的x1y1x2 等,您可以看到它是如何减少为一个值的(即描述的结果)。

当其中一个列表用完时,呼叫将是zip [] [11]。上面的等式不符合这种情况。幸运的是,您还有另一个方程式,

zip xs ys = 

它使用变量作为模式。这是一个无可辩驳模式的例子;它总是成功的。因此,无论这两个参数是什么,第一个将被称为 xs,第二个 - ys,以及等式的右侧

               [ ]

将被输入,这表明将始终生成值[]。其效果是当zip 的列表参数长度不同时,较长列表的多余元素将被忽略。

【讨论】:

    【解决方案2】:

    让我们看一个更简单的例子:

    head (x:xs) = x
    

    要意识到列表[1,2,3]1:2:3:[] 的简写,这又是1:(2:(3:[])) 的简写,因为(:) 是右关联的。所以采取

    head [1,2,3]
    

    和这个一样

    head (1:(2:(3:[])))
    

    现在我们可以看到模式与输入的相似之处。

    head (1:(2:(3:[])))
          ^  ^^^^^^^^
    head (x:   xs     )
    

    所以x 将是1xs 将是2:(3:[]),换句话说[2,3]


    稍微解释一下模式匹配。 zip的第一个等式

    zip (x:xs) (y:ys) = ...
    

    当两个列表至少有一个元素时匹配(因为空列表不是a:b 的形式)。第二个等式

    zip xs ys = ...
    

    匹配任何参数,前提是第一个方程不匹配(并且它们是正确的类型,因为 Haskell 是静态类型的)。​​

    【讨论】:

    • 真的很好!你说:“(因为空列表不是 a:b 的形式)”为什么空列表不匹配 a:b? [] = []:[] 应该匹配 a:b 和 a=[], b=[]?
    • []:[][ [] ] - 一个元素的列表(这是一个空列表)。它的头部元素是[],尾部是[]——也就是说,那里没有更多元素了。
    猜你喜欢
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    相关资源
    最近更新 更多