Proposal: Remove Semigroup and Monoid instances for Data.Map, Data.IntMap, Data.HashMap

Daniel Cartwright chessai1996 at gmail.com
Tue Feb 13 20:07:00 UTC 2018


I am strongly in favour of this as well. I do not like the newtype
approach, I think backwards-*incompatibility* with four to five year-old
(or two to three year-old) code is OK.

On Tue, Feb 13, 2018 at 3:04 PM, Daniel Cartwright <chessai1996 at gmail.com>
wrote:

> I am strongly in favour of this as well. I do not like the newtype
> approach, I think backwards-*incompatibility* with four to five year-old
> (or two to three year-old) code is OK.
>
> On Tue, Feb 13, 2018 at 2:59 PM, David Feuer <david.feuer at gmail.com>
> wrote:
>
>> I don't think the old proposal was really the right way.
>>
>> On Tue, Feb 13, 2018 at 2:54 PM, Mario Blažević <mblazevic at stilo.com>
>> wrote:
>> > +1. But whatever happened to your proposal from last May? I don't think
>> > there were any objections to it. Would the two proposals be combined, or
>> > have you decided to drop the previous one?
>> >
>> > https://mail.haskell.org/pipermail/libraries/2017-May/028036.html
>> >
>> > On 2017-05-25 12:55 PM, David Feuer wrote:
>> >> A lot of people have wrappers around Data.Map and Data.IntMap to give
>> >> them more useful (Semigroup and) Monoid instances. I'd like to add such
>> >> wrappers to containers. What we need to be able to do that are *names*
>> >> for the new modules. I can't think of any, so I'm reaching out to the
>> >> list. Please suggest names! Another question is whether we should take
>> >> the opportunity of new modules to modernize and streamline the API a
>> >> bit. I'd like, at least, to separate "safe" from "unsafe" functions,
>> >> putting the unsafe ones in .Unsafe modules.
>> >
>> >
>> >
>> > On 2018-02-13 02:33 PM, David Feuer wrote:
>> >>
>> >> Many people have recognized for years that the Semigroup and Monoid
>> >> instances for Data.Map, Data.IntMap, and Data.HashMap are not so
>> >> great. In particular, when the same key is present in both maps, they
>> >> simply use the value from the first argument, ignoring the other one.
>> >> This somewhat counter-intuitive behavior can lead to bugs. See, for
>> >> example, the discussion in Tim Humphries's blog post[*]. I would like
>> >> do do the following:
>> >>
>> >> 1. Deprecate the Semigroup and Monoid instances for Data.Map.Map,
>> >> Data.IntMap.IntMap, and Data.HashMap.HashMap in the next releases of
>> >> containers and unordered-containers.
>> >>
>> >> 2. Remove the deprecated instances.
>> >>
>> >> 3. After another several years (four or five, perhaps?), make a major
>> >> release of each package in which the instances are replaced with the
>> >> following:
>> >>
>> >>    instance (Ord k, Semigroup v) => Semigroup (Map k v) where
>> >>      (<>) = Data.Map.Strict.unionWith (<>)
>> >>    instance (Ord k, Semigroup v) => Monoid (Map k v) where
>> >>      mempty = Data.Map.Strict.empty
>> >>
>> >>    instance Semigroup v => Semigroup (IntMap v) where
>> >>      (<>) = Data.IntMap.Strict.unionWith (<>)
>> >>    instance Semigroup v => Monoid (IntMap v) where
>> >>      mempty = Data.IntMap.Strict.empty
>> >>
>> >>    instance (Eq k, Hashable k, Semigroup v) => Semigroup (HashMap k v)
>> >> where
>> >>      (<>) = Data.HashMap.Strict.unionWith (<>)
>> >>    instance (Eq k, Hashable k, Semigroup v) => Monoid(HashMap k v)
>> where
>> >>      mempty = Data.HashMap.Strict.empty
>> >>
>> >> Why do I want the strict versions? That choice may seem a bit
>> >> surprising, since the data structures are lazy. But the lazy versions
>> >> really like to leak memory, making them unsuitable for most practical
>> >> purposes.
>> >>
>> >> The big risk:
>> >>
>> >> Someone using old code or old tutorial documentation could get subtly
>> >> wrong behavior without noticing. That is why I have specified an
>> >> extended period between removing the current instances and adding the
>> >> desired ones.
>> >>
>> >> Alternatives:
>> >>
>> >> 1. Remove the instances but don't add the new ones. I fear this may
>> >> lead others to write their own orphan instances, which may not even
>> >> all do the same thing.
>> >>
>> >> 2. Write separate modules with newtype-wrapped versions of the data
>> >> structures implementing the desired instances. Unfortunately, this
>> >> would be annoying to maintain, and also annoying to use--packages
>> >> using the unwrapped and wrapped versions will use different types.
>> >> Manually wrapping and unwrapping to make the different types work with
>> >> each other will introduce lots of potential for mistakes and
>> >> confusion.
>> >>
>> >> Discussion period: three weeks.
>> >>
>> >> [*] http://teh.id.au/posts/2017/03/03/map-merge/index.html
>> >> _______________________________________________
>> >> Libraries mailing list
>> >> Libraries at haskell.org
>> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>> >>
>> >
>> > _______________________________________________
>> > Libraries mailing list
>> > Libraries at haskell.org
>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>> _______________________________________________
>> Libraries mailing list
>> Libraries at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20180213/5de417f2/attachment-0001.html>


More information about the Libraries mailing list