Data.Traversable documentation MR 5873

Viktor Dukhovni ietf-dane at
Wed Jun 2 02:58:08 UTC 2021

I hope it is acceptable on this list to solicit feedback on a
documentation MR for the base library, specifically the Data.Traversable

The rewrite touches a lot of text, and so most of you are likely to not
find time for the full review that it perhaps deserves.  But I hope that
one or two of you would be inclined to give it a go.

In addition to the specifics of the exposition, both in Data.Traversable,
and in Data.Foldable I'm opting for a somewhat new layout of the module
documentation, with just a brief blurb at the top, then all the function
synopses, and only after all that the detailed prose and laws, which
were historically at the top of each module's documentation.

I think the "prose last" format is more suitable for the typical user
who wants to quickly glance at the documentation of a single function,
or see what functions are in the module.  The detailed exposition is for
those who want to take the time to be introduced to the relevant

Section headings and links make it possible to navigate to the overview
if one is instead interested in the introductory prose.

I hope this format is a step in the right direction, or if not, this is
a good opportunity to correct the document structure.

Lastly, a comment in the MR asks whether it would be a good idea
to tweak the definitions of mapAccumL and mapAccumR to "amp up"
the use of coercions in the hope of a performance payoff.  See
proposed patch below...


diff --git a/libraries/base/Data/Traversable.hs b/libraries/base/Data/Traversable.hs
index db7e548325..6871e411a0 100644
--- a/libraries/base/Data/Traversable.hs
+++ b/libraries/base/Data/Traversable.hs
@@ -432,8 +432,10 @@ forM = flip mapM
 -- >>> mapAccumL (\a b -> (a <> show b, a)) "0" [1..5]
 -- ("012345",["0","01","012","0123","01234"])
-mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
-mapAccumL f s t = runStateL (traverse (StateL . flip f) t) s
+type TraverseL t s a b = (a -> StateL s b) -> t a -> StateL s (t b)
+mapAccumL :: forall t s a b. Traversable t
+          => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
+mapAccumL f s t = coerce (traverse :: TraverseL t s a b) (flip f) t s
 -- |The 'mapAccumR' function behaves like a combination of 'fmap'
 -- and 'Data.Foldable.foldr'; it applies a function to each element of a structure,
@@ -450,8 +452,10 @@ mapAccumL f s t = runStateL (traverse (StateL . flip f) t) s
 -- >>> mapAccumR (\a b -> (a <> show b, a)) "0" [1..5]
 -- ("054321",["05432","0543","054","05","0"])
-mapAccumR :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
-mapAccumR f s t = runStateR (traverse (StateR . flip f) t) s
+type TraverseR t s a b = (a -> StateR s b) -> t a -> StateR s (t b)
+mapAccumR :: forall t s a b. Traversable t
+          => (s -> a -> (s, b)) -> s -> t a -> (s, t b)
+mapAccumR f s t = coerce (traverse :: TraverseR t s a b) (flip f) t s
 -- | This function may be used as a value for `fmap` in a `Functor`
 --   instance, provided that 'traverse' is defined. (Using

More information about the Libraries mailing list