You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell列表元素频率计算报错:用Map.alter与foldr实现遇问题

列表频率映射代码的问题分析

1. 函数f的类型签名完全错误

foldr的第一个参数要求类型为a -> b -> b(这里b对应Map.Map a Int),但你定义的f类型是(a -> a) -> Map.Map a Int -> Map.Map a Int,把输入参数错误地声明为函数类型,完全不符合foldr的调用要求,这是编译失败的核心原因之一。

2. Map.alter的参数使用完全不符合规范

Map.alter的标准类型是(Maybe v -> Maybe v) -> k -> Map.Map k v -> Map.Map k v,参数顺序和作用是:

  • 第一个参数:处理目标键对应值的函数(接收Maybe v,返回修改后的Maybe v)
  • 第二个参数:要修改的键(类型为k,也就是这里的a)
  • 第三个参数:待修改的原Map

你的代码犯了两个关键错误:

  • 把Map.findWithDefault 0 x m + 1(一个Int数值)作为第二个参数传入,而正确的第二个参数应该是要更新的键x
  • 第一个参数传了id,这会直接返回原来的Maybe Int值,根本不会修改计数。正确的处理函数应该实现“计数加1”的逻辑:如果键不存在(值为Nothing),就返回Just 1;如果存在(值为Just n),就返回Just (n+1)。

修正后的代码

import qualified Data.Map as Map

f :: (Eq a, Ord a) => a -> Map.Map a Int -> Map.Map a Int
f x m = Map.alter (\maybeCount -> Just (maybe 0 (+1) maybeCount)) x m

freqs :: (Eq a, Ord a) => [a] -> Map.Map a Int
freqs xs = foldr f Map.empty xs

如果一定要用Map.findWithDefault,也可以这么写(不过不如上面的方式高效,因为会额外查询一次Map):

f :: (Eq a, Ord a) => a -> Map.Map a Int -> Map.Map a Int
f x m = Map.alter (\_ -> Just (Map.findWithDefault 0 x m + 1)) x m

内容的提问来源于stack exchange,提问作者coderodde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 05:35:08