A more useful Monoid instance for Data.Map
lemming at henning-thielemann.de
Sat Apr 28 10:59:45 CEST 2012
On Fri, 27 Apr 2012, wren ng thornton wrote:
> On 4/27/12 9:04 PM, Daniel Peebles wrote:
>> Currently Data.Map has a Monoid instance, but it's rather lossy and not as
>> general as it could be:
>> instance (Ord k) => Monoid (Map k v) where
>> mempty = empty
>> mappend = union
>> mconcat = unions
>> The instance would be much nicer if it required a Monoid on v and used
>> unionWith mappend instead of just union.
> I'm inclined to agree as well.
I do not know whether I used the Monoid instance already, but I know that
several times I used fromList by accident where I had to use fromListWith
I think I would also prefer your instance because the current one silently
>> I realize that changing instances could break code, but I'd be curious
>> to see how many people even use the current monoid instance. Does
>> anyone have any system for testing hypotheses like this (by
>> typechecking a large randomized chunk of hackage or something)?
> The thing I'd be more worried about is silent changes to semantics. At least
> if it doesn't typecheck then you know something went wrong; but there are
> lots of monoids and so it's very likely to typecheck but to alter semantics.
I am also worried about such changes, at least I think that the major
version number of 'containers' must be increased in order to raise
awareness. There is at least a certain chance that uses of the old
instance are detected, since the new instance requires a Monoid constraint
on the 'v' type that was not there before.
> You could try removing the instance entirely and then see how much of Hackage
> you can get to compile. That way you'll detect all uses, not just the uses
> for non-monoidal value types. You should be able to get your hands on one of
> the build-all-of-Hackage scripts people've used for this sort of thing in the
This sounds like a good idea. However I suspect that a large portion of
packages cannot be build together, because some of them rely on old
compiler versions and other ones on new versions and even more packages
rely transitively on installed foreign libraries.
Why is the Monoid instance important? Instead of mappend you can always
use explicitly Map.union or (Map.unionWith mappend). I think the instance
is important when combining different structures. E.g. in a Writer monad
the written value must a Monoid. Thus a criterion for a useful Monoid
instance could be: What is most useful for a Map as target value in a
More information about the Libraries