Let's say I have a binary tree:
data BinTree a
= Nil
| Branch a (BinTree a) (BinTree a)
I'd like to do an accumulate map on a structure like this:
mapAccum ::
(
)
=> (a -> b -> (c, a)) -> a -> BinTree b -> BinTree c
mapAccum func x Nil =
Nil
mapAccum func x (Branch y left right) =
let
(y', x') =
func x y
in
Branch y' (mapAccum func x' left) (mapAccum func x' right)
Which performs a map with an accumulator across the structure.
However this is a very general pattern. We can do this on all sorts of tree like structures, and if there's a nice, common-place abstraction I'd prefer to use that over rolling my own here.
There's a function on Traversables:
mapAccumL :: Traversable t => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
Which sort of does the same thing on lists. But it requires Foldable in a way that means it wouldn't work on binary trees. What I'm looking for would be a more basic version of this which works without Foldable.
I can make it work on types made with Cofree:
mapAccum ::
( Functor f
)
=> (a -> b -> (c, a)) -> a -> Cofree f b -> Cofree f c
mapAccum func x (y :< rest) =
let
(y', x') =
func x y
in
y' :< fmap (mapAccum func x') rest
Which shows that it's at least generally applicable to tree-like structures.
Is there a common abstraction for this function?