Haskell中WarningAccumulator的Applicative实现报错及修复咨询
错误原因与修复
错误原因
你在实现Applicative的<*>方法时,模式匹配的变量绑定顺序完全搞反了:
- 对于
WarningAccumulator w (a -> b)类型的值,构造器内部第一个元素是函数a -> b,第二个元素是警告列表[w] - 但你写的模式是
(WarningAccumulator (empty, f)),这导致f被绑定到了警告列表[w],而非预期的函数 - 当你尝试执行
f value时,f实际是列表类型[w],根本不是可调用的函数,因此编译器报错“类型[w]没有参数”
另外原实现还忽略了WarningAccumulator的核心语义——应该累积警告,而非只保留单侧的警告列表。
修复后的代码
newtype WarningAccumulator w a = WarningAccumulator (a,[w]) deriving (Show,Eq) instance Functor (WarningAccumulator w) where fmap :: (a -> b) -> WarningAccumulator w a -> WarningAccumulator w b fmap f (WarningAccumulator (value, list)) = WarningAccumulator(f value, list) instance Applicative (WarningAccumulator w) where pure :: a -> WarningAccumulator w a pure a = WarningAccumulator (a,[]) (<*>) :: WarningAccumulator w (a -> b) -> WarningAccumulator w a -> WarningAccumulator w b (<*>) (WarningAccumulator (f, warningsF)) (WarningAccumulator (value, warningsV)) = WarningAccumulator (f value, warningsF ++ warningsV)
关键修复点
- 修正
<*>模式匹配的变量顺序,让f正确绑定到函数a -> b - 用
++合并左右两边的警告列表,实现“累积警告”的设计意图
测试示例
-- 带警告的函数 addOne :: WarningAccumulator String (Int -> Int) addOne = WarningAccumulator (\x -> x+1, ["Adding one"]) -- 带警告的数值 num :: WarningAccumulator String Int num = WarningAccumulator (5, ["Got number 5"]) -- 应用后得到合并警告的结果 result = addOne <*> num -- 输出:WarningAccumulator (6,["Adding one","Got number 5"])
内容的提问来源于stack exchange,提问作者chen
相关产品推荐
相关产品推荐

