计算列表中出现的次数

我想计算 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 -> [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),因此我们首先使用n函数和t参数执行函数应用程序所以在 Python 中,这看起来像 `count(n(t))`,这不是你的意思。

那么我们如何将多个参数传递给一个函数呢?在 Haskell 中,每个函数都只有一个参数。如果你写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]计数的想法是,我们看看头,并让递归看看剩下的元素,所以条件应改为:

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

泛化类型

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

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

计数为特殊foldr函数

我们可以使用foldrfor this,而不是自己编写这个递归,这是列表上的一个catamorphismfoldr :: (a -> b -> b) -> b -> [a] -> b使用函数f :: a -> b -> b采用一个列表(一个的头a),和递归的列表(该结果b),因此,构造类型的一个新的结果b,即当为整个列表的结果。此外,该foldr函数采用一个值(类型b),该值是对应于空列表的值,然后它可以对列表 ( [a])执行此操作,并返回该列表 (a b)的值

count因此我们看一下头元素,如果它等于我们搜索的元素,我们增加“累加器”,否则我们简单地传递它,我们可以这样写计数:

count:: Eq a => a -> [a] -> Int
count n = foldr (\x -> if n == x then (+1) else id) 0

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章