Composing two folds

Viewed 94

Suppose that (from the Lens library) I have

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

and I want to combine these in such a way that

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

What is the simplest implementation of combine? (It's of course possible just to manually implement it in terms of toListOf, or the like, but I suspect a more purely compositional implementation exists.)

2 Answers

It seems that the efficient implementation is simply

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

though it's also possible to go via the ReifiedFold, though that appears to use the maybe-less-efficient toListOf implementation:

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

It took me some time to understand why the apparently asymmetric *> sufficed.

You can use (<>) directly to combine the folds:

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

As I'm overtly assuming a Monoid instance rather than relying on Fold's Applicative constraint, the types are slightly different than the ones in your (*>)-based solution. That won't matter in practice, though.

Related