【问题标题】:Find occurrences in a List using recursion in Haskell在 Haskell 中使用递归查找列表中的出现
【发布时间】:2016-04-02 01:49:26
【问题描述】:

我有一个列表,它只能包含两种元素,ApplePeach。我需要创建一个函数,给定一个包含这些元素的列表,使用递归返回列表中 Apple 的出现次数。

这是我的尝试:

data Fruit = Apple | Peach
findFruit :: [Fruit] -> Int

findFruit [] = 0

findFruit (y:ys)
    | y==Apple = 1+(findFruit ys)
    | otherwise = findFruit ys

但它不起作用。我怀疑问题出在最后的说明中,但由于我还是 Haskell 新手,我无法真正理解在哪里。

这是错误日志:

Main.hs:7:8:
    No instance for (Eq Fruit) arising from a use of ‘==’
    In the expression: y == Apple
    In a stmt of a pattern guard for
                   an equation for ‘findFruit’:
      y == Apple
    In an equation for ‘findFruit’:
        findFruit (y : ys)
          | y == Apple = 1 + (findFruit ys)
          | otherwise = findFruit ys
Failed, modules loaded: none.

感谢您的帮助!

【问题讨论】:

  • 使用模式匹配而不是守卫。正如在findFruit (Apple:xs) = ... ; findFruit (Peach:xs) = ... 中一样,添加deriving Eq 作为答案建议也将起作用,但模式匹配是惯用且更可取的。
  • 顺便说一下 - 如果你调用你的函数 findFruit 我会期待不同的类型签名,如果你这样做是为了练习尝试实现 countFruit :: Fruit -> [Fruit] -> Int

标签: haskell recursion


【解决方案1】:

您可以保持数据定义不变并使用模式匹配:

data Fruit = Apple | Peach

findFruit :: [Fruit] -> Int
findFruit []         = 0
findFruit (Apple:ys) = 1 + findFruit ys
findFruit (Peach:ys) = findFruit ys

【讨论】:

    【解决方案2】:

    您需要将deriving Eq 添加到您的类型构造函数中。这样,您的类型的相等概念将自动实现,并且 == 运算符将有效使用。

    data Fruit = Apple | Peach deriving Eq
    

    【讨论】:

      【解决方案3】:

      你的代码没问题,但他不知道如何比较元素,所以,按照编译器告诉你的那样从 eq 派生:

      data Fruit = Apple | Peach deriving (Eq)
      

      这样编译器就会有关于这个数据的信息可以进行比较。

      【讨论】:

        【解决方案4】:

        您可以尝试模块化和概念重用

        import Data.Monoid
        
        fruit a _ Apple = a    -- case analysis for Fruit 
        fruit _ p Peach = p
        
        countFruit = getSum . mconcat . map (fruit (Sum 1) (Sum 0))
        

        (虽然它不是递归的)。

        【讨论】:

        • 如果您想要模块化和概念重用,选择length . filter (Apple ==) 会容易得多。
        • @gallais 并非没有添加Eq 约束。如果你想总结价格,比如说,所有水果的价格,我的代码很容易和微不足道地允许这样做。即“易于扩展和修改”。 :)
        • 那为什么不countFruit = sum . map (fruit 1 0)呢?
        • 我只是先想到了mconcat,然后Sum是后来的细节。
        猜你喜欢
        • 2011-07-16
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        • 1970-01-01
        • 2019-07-21
        • 1970-01-01
        • 2020-01-22
        • 1970-01-01
        相关资源
        最近更新 更多