zip功能中的Haskell冒号

时间:2015-08-02 06:39:55

标签: haskell

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

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

我的想法:

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

    (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]
    

2 个答案:

答案 0 :(得分:6)

方程式左侧的(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)将不起作用(将导致编译时类型不匹配错误),因为这里的第一个参数是三元组,第二个元组是4元组;这些是列表。列表具有不同的大小,但元组具有固定的大小。因此,正确的呼叫是zip [5,7,9] [1,3,5,11]。您可以通过将数字替换为上述方案的x1y1x2等来查看它是如何减少到某个值(即描述的结果)

当其中一个列表用尽时,通话将为zip [] [11]。上述等式与此情况不符。幸运的是,你有另一个等式,

zip xs ys = 

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

               [ ]
将输入

,表示将始终生成值[]。它的作用是当zip的列表参数长度不同时,更长列表的额外元素将被忽略。

答案 1 :(得分:5)

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

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     )

因此x1xs2:(3:[]),换言之[2,3]

阐述一下模式匹配。 zip

的第一个等式
zip (x:xs) (y:ys) = ...
当两个列表至少有一个元素时,

匹配(因为空列表的格式不是a:b)。第二个等式

zip xs ys = ...

匹配任何参数,只要第一个等式不匹配(并且它们是正确的类型,因为Haskell是静态类型的)。​​