A more useful Monoid instance for Data.Map

Milan Straka fox at ucw.cz
Tue Mar 12 17:40:13 CET 2013

Hi all,

> -----Original message-----
> From: Ben Gamari <bgamari.foss at gmail.com>
> Sent: 12 Mar 2013, 11:06
> <snip>
> We should take advantage of this opportunity to begin an easy cleanup
> and accept that there are still other issues that will need to be dealt
> with once the tools for doing so exist.

IIRC, the instances we are talking about are

  instance (Ord k) => Monoid (Map k v) where
    mempty  = empty
    mappend = union
    mconcat = unions

  instance (Ord k, Monoid v) => Monoid (Map k v) where
    mempty            = empty
    mappend map0 map1 = unionWith mappend map0 map1
    mconcat maps      = foldr (unionWith mappend) empty maps
or even
  instance (Ord k, Semigroup v) => Monoid (Map k v) where
    mempty            = empty
    mappend map0 map1 = unionWith <> map0 map1
    mconcat maps      = foldr (unionWith <>) empty maps

I am not convinced that the proposed instance is universally the best
one. I like the current instance -- I sometimes use it on
Map k v where v is a "primitive" type like Int or Double for which no
Monoid instance exists. Personally, I am also not sure that
  fromList [(1, "A")] `mappend` fromList [(1, "B")
should really be
  fromList [(1, "AB")]

The price for any change is very high:
a) silent semantic change for replacing the instance is a no go,
   consider for example for Map k String or Map k ByteString.
b) removing and then adding the instance means we will have two major
   version bumps. That places a burden on every user of the library to
   at least upgrade upper bounds. And as Edward Kmett wrote earlier
   today, the users that want to use the Monoid instance must revert to
   some kind of conditional compilation.

I am not saying we should never do any breaking changes, but in this
case, the benefit seems rather small to me.

So -1 on changing the Monoid instance from me.

Milan Straka

More information about the Libraries mailing list