为何Data.Bitraversable没有类似Data.Bifunctor的traverseFirst/traverseSecond方法
为什么Data.Bitraversable没有内置traverseFirst/traverseSecond方法
首先要澄清两个基础事实:
- 这两个功能完全可以通过
Bitraversable的核心方法bitraverse直接实现,不需要额外定义类型类成员 - 较新版本的
base库已经在Data.Bitraversable模块中直接导出了这两个工具函数,不需要自己实现
手动实现逻辑
Bitraversable的核心方法bitraverse类型如下:
bitraverse :: (Bitraversable t, Applicative f) => (a -> f c) -> (b -> f d) -> t a b -> f (t c d)
要实现仅处理第一个/第二个类型参数的遍历,只需要给另一个参数传入pure(也就是不做任何效果性操作,直接把原值包进Applicative上下文)即可:
-- 遍历第一个参数 traverseFirst :: (Bitraversable t, Applicative f) => (a -> f c) -> t a b -> f (t c b) traverseFirst f = bitraverse f pure -- 遍历第二个参数 traverseSecond :: (Bitraversable t, Applicative f) => (b -> f d) -> t a b -> f (t a d) traverseSecond g = bitraverse pure g
没有纳入类型类定义的原因
类型类的方法设计会尽量精简,仅保留无法通过其他方法衍生、或者有强性能优化需求的操作:
- 只要
bitraverse的实现符合Bitraversable的定律,上面两个衍生函数的行为就一定会符合预期,不需要类型类的实现者额外编码 - 这类衍生操作的手动优化空间极低,没有必要像
Bifunctor那样把first/second设为可选的类方法,额外增加类型类实现的负担 - 如果需要高性能的定制实现,你完全可以在自己的项目中针对特定的
Bitraversable实例写特化版本,不需要修改标准库的类型类定义
内容的提问来源于stack exchange,提问作者bwroga
相关产品推荐
相关产品推荐

