如何在Haskell中编写Foldable类型的fsum函数?
实现Foldable容器的求和函数(针对Num类型)
你遇到的核心问题是Num类型本身没有默认的Monoid实例(因为加法和乘法都符合幺半群规则,Haskell不会自动二选一),但我们有两种简单的方式实现fsum:
方法1:借助Sum幺半群包装器(推荐)
利用base库自带的Sum newtype,它给Num类型提供了加法幺半群的实例,结合Foldable的foldMap方法实现:
import Data.Monoid (Sum(Sum, getSum)) fsum :: (Foldable f, Num a) => f a -> a fsum = getSum . foldMap Sum
Sum把Num值包装成具备加法幺半群特性的类型(单位元为0)foldMap会遍历容器,将每个元素转换为Sum a后折叠累加getSum最终把结果从Sum包装中提取出来
调用示例:
fsum [1, 2, 3] -- 输出 6 fsum (Just 5) -- 输出 5 fsum (Nothing :: Maybe Int) -- 输出 0
方法2:手动用foldr/foldl实现
直接使用Foldable的折叠函数,指定初始值和累加逻辑:
fsum :: (Foldable f, Num a) => f a -> a fsum = foldr (+) 0
或者用foldl(性能上对于严格求值的类型有差异,但逻辑一致):
fsum = foldl (+) 0
这里初始值用Num的加法单位元0,累加函数直接用加法运算符(+),本质上和方法1的逻辑完全一致,只是更直观,不需要引入Monoid相关的类型。
调用示例和方法1完全相同,所有Foldable类型(列表、Maybe、Tree等)都能直接使用。
内容的提问来源于stack exchange,提问作者RunTimeError31415
相关产品推荐
相关产品推荐

