inOrder函数中的模式匹配

时间:2013-10-02 18:55:40

标签: design-patterns haskell pattern-matching matching

我刚开始使用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是否有可能,如何在没有警卫的情况下编写此功能?

感谢您花时间阅读。如果有什么不清楚,我道歉。 任何帮助,提示或有用的链接都表示赞赏。

3 个答案:

答案 0 :(得分:2)

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

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)

答案 1 :(得分:0)

您需要进行递归调用:

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

你为什么不写守卫?

答案 2 :(得分:0)

你正准备回答你几乎肯定想要上课的答案。但是我想建议另一种方法更接近你想要在生产代码中做的事情:即,自己编写一小部分特定于域的逻辑,但重用现有的高阶函数用于递归逻辑。在这么小的例子中,很难看到好处;但是,习惯于这种关注点的分离对于大型工程项目有很大帮助。这是一个看起来如何的例子。

-- 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而没有其他辅助功能。 (通过支付此对数运行时成本获得的优势是此代码非常短 - 并且很难隐藏短代码中的错误!)

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