【问题标题】:Pattern matching within an inOrder functioninOrder 函数中的模式匹配
【发布时间】:2013-10-02 18:55:39
【问题描述】:

我刚刚开始 Haskell 编程,之前从未使用过函数式语言。

我正在尝试使用模式匹配编写一个函数,该函数将测试给定的整数列表是否按升序排列。如果是则返回 true,否则返回 false。

inorder :: [Integer] -> Bool
inorder [] = True
inorder [x] = True
inorder (x:y:t) | x<=y && y<=head t = True
        | otherwise = False

目前仅比较给定列表的前两个元素。

Q1 当列表中前面有一个整数时,我将如何将每个整数与其前面的整数进行比较?

这是作业,我想使用模式匹配而不是保护方程来完成,但我不得不同时使用这两种方法,因为我不确定模式匹配相当于“否则”是什么。

Q2 有可能吗?如果没有警卫,我将如何编写这个函数?

感谢您抽出宝贵时间阅读。如果有任何不清楚的地方,我很抱歉。 感谢您提供任何帮助、提示或有用的链接。

【问题讨论】:

  • 将 (x:y:t) 声明为第一个模式是有意义的。然后你只需要inorder _ = True 来匹配其余的情况。这给您带来的是单个模式匹配(匹配x:y:t,或继续),而不是匹配的三个模式。虽然这个顺序起初可能会让人觉得“错误”。

标签: design-patterns haskell pattern-matching matching


【解决方案1】:

Q1. 使用递归。您比较前两个值,然后对剩余的列表执行相同的操作,其中仍然包含第二个值,因此它与原始列表的第三个值进行比较:

inorder (x:y:t)
  | x <= y && inorder (y:t) = True -- We included y in the call to inorder
  | otherwise = False

Q2. 是的,这是可能的。请注意,在前面的函数中,当给定术语为 True 时,我们返回 True,否则返回 False。这意味着我们可以只返回术语的值,而不是使用守卫:

inorder (x:y:t) = x <= y && inorder (y:t)

【讨论】:

    【解决方案2】:

    你需要进行递归调用:

    inorder (x:y:t) | x<=y = inorder (y:t)
                    | otherwise = False
    

    你为什么要在没有警卫的情况下写作?

    【讨论】:

    • 这是我的讲师设定的使用模式匹配解决的众多任务之一。感谢您的及时回复。
    【解决方案3】:

    您正在寻找几乎可以肯定想要上交课堂作业的答案。但我想提出另一种更接近于您希望在生产代码中执行的操作的方法:即,自己编写一点特定于域的逻辑,但将现有的高阶函数重用于递归逻辑。在这样一个小例子中,很难看到好处;但是习惯这种关注点分离对大型工程项目有很大帮助。这是一个外观示例。

    -- this is the domain-specific logic
    frontInOrder (x:y:_) = x <= y
    frontInOrder _ = True
    
    -- here we do the recursion by handing the list off to tails/all
    inOrder = all frontInOrder . tails
    

    当然,frontInOrder 本身可以被大量丢弃。你可能会想到这样的事情,例如,甚至没有任何模式匹配:

    sorted xs = sort xs == xs
    frontInOrder = sorted . take 2
    inOrder = all frontInOrder . tails
    

    如果线性时间和线性时间之间的差异对您的应用程序来说不是太重要,您甚至可以只考虑 inOrder xs = sort xs == xs 而没有其他辅助功能。 (支付这种对数运行时成本的好处是这段代码非常短——而且很难在短代码中隐藏错误!)

    同样,我不建议在您的锻炼解决方案中执行此类操作:首先,您绝对应该手动编写几百个函数。但是一旦你开始发现一些模式,你就绝对应该寻找代码重用的机会。

    【讨论】:

      猜你喜欢
      • 2012-01-25
      • 2016-04-26
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2014-12-22
      相关资源
      最近更新 更多