【问题标题】:Haskell - finding smallest Element in listHaskell - 在列表中找到最小的元素
【发布时间】:2017-07-20 16:27:10
【问题描述】:

我有一个函数,它获取一个列表并且必须返回它的最小元素。

不幸的是,我一直遇到这个问题:

模式中的解析错误:最小

我做错了什么?

minim :: [Int] -> Int
minim []       = 0
minim [x]      = x
minim x:xs     = min x (minim xs)

min :: Int -> Int -> Int
min a b
    | a > b  = b
    | a < b  = a

【问题讨论】:

  • 你在 min 中也缺少一个 case,其中 a 和 b 相等
  • 我已添加 | a == b = 0。现在我得到了问题:模棱两可的出现“主要”。我之前保存并重新编译过文件。
  • 这个单线怎么样? foldl (\x y-&gt;if x&lt;y then x else y) (maxBound::Int) [2,5,2,3,5]

标签: haskell recursion functional-programming pattern-matching parse-error


【解决方案1】:

使用minimum

> minimum [2, 1, 3]
> 1

【讨论】:

    【解决方案2】:

    这个函数不应该使用列表,因为想出一个最小值是没有意义的,例如0 表示空列表,当元素类型甚至可能允许负值时。为了保证安全性和通用性,我们可以使用Min type。首先,让我们做一个输入值的例子:

    exampleList = 1 :| [2, 3, 4]
    

    :| 是非空列表的构造函数,比较适合。

    要找到最小值,我们可以使用 sconcat,它使用 Semigroup 操作组合非空列表的所有元素,在这种情况下,这就像在其他答案中显示的两个元素上的 min 函数.

    > sconcat $ fmap Min exampleList
    Min {getMin = 1}
    

    要从Min 中提取号码,您可以使用getMin

    【讨论】:

      【解决方案3】:

      这是实现您所要求的另一种方法,但不必使用诸如 min 之类的辅助函数

      minElem::[Int]->Int
      minElem [] = 0
      minElem [x] = x
      minElem (x:y:xs) 
       |x > y = minElem (y:xs)
       |x < y = minElem (x:xs)
       |x == y = minElem (x:xs)
      

      【讨论】:

        【解决方案4】:

        您有一个要匹配的参数(Ints 的列表)。如果您想匹配该列表的某些部分,您需要将它们放在括号中以显示您正在匹配一件事的编译器。因此最后一个模式应该是(x:xs)

        【讨论】:

        • 您的解释对我来说似乎是正确和合乎逻辑的。不幸的是,对于 'minim x:[] = x' 我仍然在解析模式中遇到错误。
        • @jublikon: 我发现了第二个问题!
        • [x] 是匹配一个列表的完美(更清晰)的方式。
        • @KarlBielefeldt:啊,我没有意识到,我一直使用 cons 运算符(所以当被告​​知存在语法错误但不是哪一行对我来说看起来不对时)。
        • @dave 许多人希望看到错误信息已从 SO 答案中删除。因此,我恳请您相应地编辑您的。
        【解决方案5】:

        如果你想用最 Haskell 的方式解决它。我会这样解决它:

        -- Does not work for empty lists (so maybe needs to be wrapped in some logic)
        foldr1 min [-3,1,2,3]
        -- Works for empty but needs a "default value" (in this case 0)
        foldr min 0 [-3,1,2,3]
        

        如果你想通过自己实现它来学习,那么这对我有用

        minim :: [Int] -> Int
        minim []       = 0
        minim [x]      = x
        minim (x:xs)   = min x (minim xs)
        
        min :: Int -> Int -> Int
        min a b
            | a > b  = b
            | a < b  = a
            | a == b = a
        

        但是我会让它更安全一点,因为如果它是空的,0 真的是列表中最小的 int 吗?我认为你应该使用Nothing 作为结果。

        import Data.Maybe
        
        import Prelude hiding (min)
        
        main = print $  minim [1,3,4, 6,6,-9]
        
        minim :: [Int] -> Maybe Int
        minim []       = Nothing
        minim [x]      = Just x
        minim (x:xs)   = min x <$> minim xs
        
        min :: Int -> Int -> Int
        min a b
            | a > b  = b
            | a < b  = a
            | a == b = a
        

        【讨论】:

        • 0 对于min 来说是一个非常糟糕的初始化程序,你不觉得吗?也许minim [] = 1/0
        • minim 的第三个等式非常尴尬,fromJust 调用和Just 的另一个提及也是如此。最好是:minim (x:xs) = min x &lt;$&gt; minim xs.
        • @amalloy,感谢您的建议,觉得那里有“Just”有点奇怪,但没有让它发挥作用。对 (或 Functors/monads)不太熟悉,但现在我学到了一些东西,谢谢 :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-07
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 2013-01-11
        • 1970-01-01
        • 2021-10-10
        相关资源
        最近更新 更多