组成两个折叠

Composing two folds

假设(来自镜头库)我有

fold1 :: Fold s a
fold2 :: Fold s a

我想以这样的方式组合这些

toListOf (combine fold1 fold2) s == toListOf fold1 s ++ toListOf fold2 s

combine最简单的实现是什么? (当然可以根据 toListOf 等手动实现它,但我怀疑存在更纯粹的组合实现。)

看来高效的实现简直了

combine f1 f2 k s = f1 k s *> f2 k s

尽管也可以通过 ReifiedFold,尽管这似乎使用了效率可能较低的 toListOf 实现:

combine f1 f2 = runFold (Fold f1 <> Fold f2)

我花了一些时间才明白为什么明显不对称的 *> 就足够了。

可以直接使用(<>)组合折叠:

ghci> [1..4] ^.. (folded . filtered even <> backwards folded)
[2,4,4,3,2,1]

由于我公开假设 Monoid 实例而不是依赖 FoldApplicative 约束,因此类型与 中的略有不同.不过,这在实践中并不重要。