在Haskell中使用递归查找列表中的引用
我有一个只包含两种元素的列表,Apple和Peach。我需要创建一个函数,给定一个包含这些元素的列表,通过递归返回列表中出现的Apple 以下是我的尝试:在Haskell中使用递归查找列表中的引用,haskell,recursion,Haskell,Recursion,我有一个只包含两种元素的列表,Apple和Peach。我需要创建一个函数,给定一个包含这些元素的列表,通过递归返回列表中出现的Apple 以下是我的尝试: 数据水果=苹果|桃 findFruit::[Fruit]->Int findFruit[]=0 findFruit(y:ys) |y==苹果=1+(findFruit ys) |否则=findFruit ys 但它不起作用。我怀疑问题在最后的说明中,但我不能真正理解在哪里,因为我仍然是Haskell的新手 以下是错误日志: Main.hs:
数据水果=苹果|桃
findFruit::[Fruit]->Int
findFruit[]=0
findFruit(y:ys)
|y==苹果=1+(findFruit ys)
|否则=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.
谢谢你的帮助 您需要向类型构造函数添加
派生Eq
。这样,类型的相等概念将自动实现,并且==运算符将有效使用
data Fruit = Apple | Peach deriving Eq
您的代码还可以,但他不知道如何比较元素,因此,正如编译器告诉您的那样,只需从eq派生:
data Fruit = Apple | Peach deriving (Eq)
这样,编译器就可以比较有关此数据的信息。您可以保持数据定义不变,并使用模式匹配:
data Fruit = Apple | Peach
findFruit :: [Fruit] -> Int
findFruit [] = 0
findFruit (Apple:ys) = 1 + findFruit ys
findFruit (Peach:ys) = findFruit ys
您可以尝试使用
import Data.Monoid
fruit a _ Apple = a -- case analysis for Fruit
fruit _ p Peach = p
countFruit = getSum . mconcat . map (fruit (Sum 1) (Sum 0))
(虽然不是递归的)。使用模式匹配而不是保护。正如在
findFruit(Apple:xs)=;findFruit(Peach:xs)=……
添加导出Eq
,正如答案所示,也会起作用,但模式匹配是惯用的,更可取。顺便说一下,如果你调用函数findFruit
,我会期望一个不同的类型签名,如果你把它作为一个练习,试着实现countFruit::Fruit->[Fruit]->Int
。如果您想要模块化和概念重用,那么选择长度要容易得多。过滤器(Apple==)
@gallais必须添加Eq
约束。如果你想计算所有水果的价格,比如说,我的代码很容易做到这点。i、 e.“易于扩展和修改”。)为什么不countFruit=sum。地图(水果10)
然后呢?我只是先想到了mconcat
,而Sum
是后来的细节。