0

我刚刚开始 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 有可能吗?如果没有警卫,我将如何编写这个函数?

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

4

3 回答 3

2

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)
于 2013-10-02T19:10:29.840 回答
0

您需要进行递归调用:

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

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

于 2013-10-02T19:03:07.820 回答
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或者,如果线性时间和线性时间之间的差异对您的应用程序不太重要,您甚至可以考虑不使用其他辅助功能。(支付这种对数运行时成本的好处是这段代码非常短——而且很难在短代码中隐藏错误!)

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

于 2013-10-02T19:44:28.133 回答