从列表中获取最大数量

时间:2018-02-18 23:16:21

标签: haskell recursion

我正在尝试使用Maybe& amp从列表中获取最大数量只是和递归。我已经找到了递归部分,但无法理解使用

的正确语法

Haskell代码 ..

Max :: [Int] -> Maybe Int
Max [_] = []
Max (x:xs)
    | x > (Max xs) = Just x
    | otherwise = Max xs

输入

Max [1,2,78]
Max [-99,-12,-37]

编译错误消息

  *Main> :l max.hs
  [1 of 1] Compiling Main             ( max.hs, interpreted )

  max.hs:2:14: error:
* Couldn't match expected type `Maybe Int' with actual type `[a0]'
* In the expression: []
  In an equation for `Max': Max [_] = []
 |
 2 | Max [_] = []
 |              ^^

 max.hs:4:16: error:
* Couldn't match expected type `Int' with actual type `Maybe Int'
* In the second argument of `(>)', namely `(Max xs)'
  In the expression: x > (Max xs)
  In a stmt of a pattern guard for
                 an equation for `Max':
    x > (Max xs)
 |
 4 |         | x > (Max xs) = Just x
 |                ^^^^^^^^^
 Failed, no modules loaded.

2 个答案:

答案 0 :(得分:2)

语法isn' 重要。更重要的是要了解 为什么你想要回复Maybe Int而不是Int 第一名。

整数是完全有序的集合,但没有最小 (小于或等于任何其他元素的元素)。因此, 如果返回类型只是Int,那么人们就不知道要为空列表返回什么。 从概念上讲,人们希望返回类似“负面”的东西 无穷大",但这不是一个合适的整数。

相反,我们可以做以下事情。我们定义一个新的完全有序的集合 Maybe Int,其中

  • Just n对应普通整数n
  • Nothing对应于"负无穷大"

在比较Just nJust m时,我们只是比较nm。 将Just nNothing进行比较时,Just n应始终如此 大于Nothing。也就是说,Nothing变为人为添加 "负无穷大" - 最小元素。

现在,由于list数据类型有两个构造函数(空列表和 头部元素cons编辑到尾部),我们需要两种情况:

  • 如果列表为空,则返回人工"负无穷大"元件
  • 如果列表非空,头部为x,请将Just x与尾部的最大值进行比较。

比较时,我们必须区分尾部最大的情况 可以是NothingJust m

总而言之,我们获得了类似的东西:

findMax :: [Int] -> Maybe Int
findMax [] = Nothing
findMax (x:xs) = 
  case (findMax xs) of
    Nothing -> Just x
    Just m -> if x > m then Just x else Just m

main = print $ show $ findMax [22, 23, 52, 21, 33, 71, 15, 18, 34]

请注意,我将Max重命名为findMax,因为函数名称应以小写字母开头。

答案 1 :(得分:1)

您的代码中似乎有几个问题需要解决:

(1)函数名通常在Haskell中以小写开头

(2)考虑到(1),我们可能不想覆盖Prelude中的max

(3)第一行与列表中的内容匹配:Max [_] = []表示如果_是最大的,我们会得到错误的答案:)

(4)(3)中的行返回[],这不是Maybe类型。返回Nothing而不是

(5)我们需要一个"最低"要匹配的号码。安德烈的回答提供了一个很好的概念选择。我已经为更加肮脏而又古怪的-1/0寻找了一个非常低的数字。

希望这有帮助!

import Data.Maybe

myMax :: [Int] -> Maybe Int
myMax [] = Nothing
myMax (x:xs)
    -- we need fromMaybe here because we can't `>` with Nothing
    | x > fromMaybe (floor(-1/0)) (myMax xs) = Just x
    | otherwise = myMax xs

main = print(myMax [1,2,78])