【问题标题】:Explain this 'Merge' Function in Haskell在 Haskell 中解释这个“合并”函数
【发布时间】:2013-12-10 15:58:06
【问题描述】:

我正在学习 Haskell,但我无法理解这个功能。我正在实施合并排序。我实现了合并排序递归函数,但我不明白这个“合并”函数在做什么。我理解命令式语言中的归并排序,但我不理解这里的语法。

merge []         ys                   = ys
merge xs         []                   = xs
merge xs@(x:xt) ys@(y:yt) | x <= y    = x : merge xt ys
                          | otherwise = y : merge xs yt

【问题讨论】:

  • 从我看到的这个函数合并两个排序列表,并返回一个排序列表。你有什么不明白的?是语法吗?
  • 是的,看我的编辑。谢谢。

标签: sorting haskell mergesort


【解决方案1】:
merge []         ys                   = ys

如果第一个参数为空,则给出第二个参数。

merge xs         []                   = xs

如果第二个参数为空,则给出第一个参数。

merge xs@(x:xt) ys@(y:yt) | x <= y    = x : merge xt ys
                          | otherwise = y : merge xs yt

如果x 小于或等于y,则将xs 的其余部分(即xt)与ys 合并的结果为x(添加到前面)。否则 y 会更小,因此将其与 xs 与 ys 的其余部分(即 yt)合并的结果相结合。

xs@(x:xt) 是使用“占位符”的参数解构。结果是xs 将引用整个第一个参数,而x 是头部,xt 是尾部。

由于merge是递归定义的,它会继续从xs和ys中cons元素,直到至少有一个为空,然后简单地返回它。

竖线 (|) 表示 "guards",让您可以以简洁明了的方式定义条件。

【讨论】:

  • xs@(x:xt) 和 ys@(y:yt) 签名呢?
  • @csreap3r 添加了对占位符的解释
  • 那么“管道”的使用基本上是条件语句吗?
  • 是的!他们被称为“守卫”
  • @csreap3r 我推荐阅读learnyouahaskell.com 这是一本了不起的书
【解决方案2】:

让我们逐行分解:

  1. merge [] ys = ys

    此行模式匹配第一个列表。如果第一个列表是空列表(即[]),则返回第二个列表。

  2. merge xs [] = xs

    和以前一样,只是列表角色颠倒了。

  3. merge xs@(x:xt) ys@(y:yt)

    (x:xt) 这样的模式匹配仅在列表元素非空时才匹配。如果匹配,x 设置为第一个元素,xt 设置为列表的其余部分。请记住,: 是列表构造运算符(即1 : [2, 3] == [1, 2, 3])。 xs@... 前缀意味着整个列表设置为xs。如果您需要同时参考整个列表以及它的头部和尾部,这将非常有用。

【讨论】:

    【解决方案3】:

    函数模式匹配它的两个参数。让我们看一下每个单独的子句:

    merge []         ys                   = ys
    

    因此,合并一个空列表和另一个列表 ys 会得到 ys。

    merge xs         []                   = xs
    

    这就像第一个子句,只是反过来:合并一个列表 xs 和一个空列表得到 xs。

    merge xs@(x:xt) ys@(y:yt) | x <= y    = x : merge xt ys
                              | otherwise = y : merge xs yt
    

    这是递归子句。这里的函数模式匹配它的两个参数,所以:

    • xs 是第一个列表,并被解构(通过 as 模式)为头部 x 和尾部 xt
    • ys 是第二个列表,解构为头部y 和尾部yt

    现在,如果第一个列表的头部小于或等于第二个列表的头部(第一个守卫),那么结果就是第一个列表的头部y,然后是合并尾部的结果第一个列表(这是xt)和第二个列表ys。如果y 小于x,我们会做相反的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-04
      • 2010-10-28
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多