计算列表中的出现次数

时间:2018-06-09 09:25:48

标签: 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)

1 个答案:

答案 0 :(得分:7)

这里有两个问题:错误与正确的语法有关,还有语义错误。

使用“多个”参数调用函数

编译器可能抱怨的错误与粗体部分有关:

count:: Int -> [Int] -> Int
count n []= 0
count n (h:t) | (n `elem` (h:t)) = 1+ count (n t)
              | otherwise = count (n t)

对于大多数首先使用其他语言编程的程序员来说,有些事情是使用括号进行功能应用。实际上,在许多编程语言中,如果有人编写foo(1),那么在Haskell中你可以编写foo 1

结果Haskell解释了这样一个事实:你写count (n t)是因为count的参数是(n t),因此我们首先使用{{1}执行了函数应用程序函数和n参数。所以在Python中,这看起来像`count(n(t))``,这不是你的意思。

那么我们如何将多个参数传递给函数?好吧,在Haskell中,每个函数都有一个参数。如果你写t,你基本上构建了一个 new 函数。通过将第二个参数应用于该新函数,我们因此“链接”函数应用程序,如count n,因此我们可以用以下方法解决语法错误:

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将导致count 3 [1, 2, 3, 4]。由于3出现3[1, 2, 3, 4][2, 3, 4]。计数的想法是我们查看头部,并让递归查看剩余的元素,因此条件应替换为:

[3, 4]

推广类型

现在我们可以使函数更通用:让函数在具有不同类型对象的列表上工作。事实上,只有一件事限制了这些类型:我们需要能够对其执行(==) :: Eq a => a -> a -> Bool,因此我们可以将类型签名概括为:

count:: Int -> [Int] -> 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 [] = 0 count n (h:t) | n == h = 1 + count n t | otherwise = count n t函数

我们可以使用foldr来代替自己编写此递归,这是列表中的 catamorphism foldr :: (a -> b -> b) -> b -> [a] -> b使用一个函数foldr,它取一个列表的头部(f :: a -> b -> b),以及列表中的递归结果(a),从而构造类型为b的新结果,然后是整个列表的结果。此外,b函数接受一个值(类型为foldr),该值是与空列表对应的值,然后它可以在列表(b)上执行此操作,并返回该列表的值([a])。

我们的b因此看一下head元素,如果它等于我们搜索的元素,我们递增“累加器”,否则我们只是传递它,因此我们可以将count计为: / p>

count