List 在列表中计算发生的事件
我想计算Haskell中列表中元素的出现次数,但出现了一个错误,我不知道为什么List 在列表中计算发生的事件,list,haskell,count,List,Haskell,Count,我想计算Haskell中列表中元素的出现次数,但出现了一个错误,我不知道为什么 count:: Int -> [Int] -> Int count n []= 0 count n (h:t) | (n `elem` (h:t)) =1+ count (n t) | otherwise = count(n t) 这里有两个问题:一个是与正确语法有关的错误,另一个是语义错误 使用“多个”参数调用函数 编译器可能抱怨的错误与黑体部分有关: count:: Int ->
count:: Int -> [Int] -> Int
count n []= 0
count n (h:t) | (n `elem` (h:t)) =1+ count (n t)
| otherwise = count(n t)
这里有两个问题:一个是与正确语法有关的错误,另一个是语义错误 使用“多个”参数调用函数 编译器可能抱怨的错误与黑体部分有关:
count:: Int -> [Int] -> Int
count n []= 0
count n (h:t) | (n `elem` (h:t)) = 1+ count (n t)
| otherwise = count (n t)
语义错误:elem
而不是=
?
但是现在仍然有一个语义错误:n`elem`(h:t)
会做什么?实际上,它将检查n
是否出现在列表中。它本身并不在头脑中,因此,在某些情况下,我们的函数将对一个值进行多次计数。例如,计数3[1,2,3,4]
将导致3
。由于3
发生[1,2,3,4]
,[2,3,4]
和[3,4]
。计数的思想是,我们只看头部,让递归看其余的元素,因此条件应替换为:
count:: Int -> [Int] -> Int
count n [] = 0
count n (h:t) | n == h = 1 + count n t
| otherwise = count n t
作为特殊的foldr
功能进行计数
我们可以使用foldr
来实现这个递归,而不是自己编写这个递归,这是列表中的一个反同构。使用函数f::a->b->b
,该函数取列表的头(aa
)和列表上的递归结果(ab
),从而构造类型为b
的新结果,然后是整个列表的结果。此外,foldr
函数获取一个值(类型为b
),该值是对应于空列表的值,然后它可以对列表([a]
)执行此操作,并返回该列表的值(ab
)
因此,我们的count
会查看head元素,如果它等于我们搜索的元素,我们会增加“累加器”,否则我们只需传递它,我们就可以将count写为:
count:: Eq a => a -> [a] -> Int
count n = foldr (\x -> if n == x then (+1) else id) 0
什么错误?你认为这意味着什么?无法将预期的类型“Int”与实际类型“[Int]->Int”匹配另一种思考
foldr f z
的有用方法是,给定一个类似[1,2,3,4]
的列表,它在内部是1:(2:(3:[])
,它将替换所有的(:)
调用f
的构造函数和[]
调用z
的构造函数,给出1`f`(2`f`(3`f`(4`f`z))
=f1(f2(f4z))
-在这种情况下,(如果n==1…(如果n==2…(如果n==3((如果n==4…)0))
,对于n=3
而言,其计算结果为id(id((+1)(id 0))
=0+1
=1
。
count:: Eq a => a -> [a] -> Int
count n [] = 0
count n (h:t) | n == h = 1 + count n t
| otherwise = count n t
count:: Eq a => a -> [a] -> Int
count n = foldr (\x -> if n == x then (+1) else id) 0