foldl icon indicating copy to clipboard operation
foldl copied to clipboard

How to replicate a Fold inside sublists?

Open guillaumecherel opened this issue 5 years ago • 4 comments

I was looking for a way to compute the mean of a list of lists "by column", i.e. compute the mean of the first elements of the sublists, the second elements, etc. I looked for a way to transform Fold.mean :: Fold Double Double into a Fold [Double] [Double]. I couldn't find a way so I wrote the function below. My question is: did I miss a better, perhaps applicative-style way to do it?

foldZ :: Fold a b -> Fold [a] [b]
foldZ (Fold s i e) = 
  Fold (\xs as -> zipWith s xs as)
         (repeat i)
         (\xs -> fmap e xs)

guillaumecherel avatar Oct 02 '19 13:10 guillaumecherel

@guillaumecherel: No, there isn't a better approach that I'm aware of when the number of list elements is not fixed.

If there were a fixed number of elements (such as a 2-tuple pretending to be a list of 2 elements), then the solution would be:

(,) <$> handles _1 mean <*> handles _2 mean
    :: (Fractional a, Fractional b) -> Fold (a, b) (a, b)

Gabriella439 avatar Oct 03 '19 16:10 Gabriella439

Does it look to you like an addition to the folds worth doing a pull request?

guillaumecherel avatar Oct 07 '19 07:10 guillaumecherel

@guillaumecherel: Yeah!

What I just noticed is that this can actually be generalized to any Applicative, like this:

nest :: Applicative f => Fold a b -> Fold (f a) (f b)
nest (Fold s i e) = 
  Fold (\xs as -> liftA2 s xs as)
         (pure i)
         (\xs -> fmap e xs)

foldZ then becomes the special case where f = ZipList

Gabriella439 avatar Oct 09 '19 03:10 Gabriella439

Right, nice! I'll prepare something with this.

guillaumecherel avatar Oct 09 '19 07:10 guillaumecherel