haskell / containers

Assorted concrete container types

Home Page:https://hackage.haskell.org/package/containers

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Make foldMap1 for Data.Tree follow the structure

treeowl opened this issue · comments

foldMap1 is implemented in terms of foldrMap1, which is ... not great. foldMap1 should (usually) follow the natural structure of a type. Consider the case where someone decides to use foldMap1 to implement their own copy of last:

import Data.Semigroup (Last (..))
myLast :: Tree a -> a
myLast = getLast . foldMap1 Last

As currently implemented, this will walk the entire tree in pre-order, which could run us into trouble in an infinite subtree, or slow us down with a large one.

@meooow25 Let's get this fixed before release (very, very soon).

Are there any other folds that accidentally got overly linearized like this? The strict folds are inherently linear, I believe.

I wasn't aware that this is something to consider, but I can see the utility of implementing it that way.

Are there any other folds that accidentally got overly linearized like this?

foldMap is defined via Traversable, so that should be fine. I don't think there is anything else.

Yes, foldMap and foldMap1 strictness always require careful consideration. Consider

import Data.Functor.Reverse
data Stream a = a :< Stream a
  deriving Foldable
data Foo a = Foo (Stream a) (Reverse Stream a)
  deriving Foldable 

The derived foldMap for Foo will correctly support folding from either end, despite the fact that foldr will never reach the right side and foldl will never reach the left side.