Discussion:
Deprecate First and Last in Data.Monoid
Andrew Martin
2018-04-11 23:46:00 UTC
Permalink
I propose that the data types First and Last, provided by Data.Monoid, be marked deprecated in GHC 8.6 and removed in GHC 8.10. The Semigroup-Monoid Proposal (SMP) brought about changes that, I will argue, make these data types (1) unneeded and (2) confusing.

Why are they no longer needed? Data.Semigroup provides two identically named data types (First and Last). These have Semigroup instances matches what their names suggest. Additionally, SMP corrects the Monoid instance for Maybe so that it now lifts Semigroup instances instead of Monoid instances. What this means is that, assuming the following imports:

import qualified Data.Monoid as M
import qualified Data.Semigroup as S

We have the following equivalences:

M.First a === Maybe (M.First a)
M.Last a === Maybe (M.Last a)

When I say "equivalence", I mean that their Monoid instances have the same behavior. Their Show/Read instances are certainly different, and I’m not sure about their Ord instances.

Getting back to the second reason, removing these data types would eliminate confusion. It’s strange that Semigroup is a superclass of Monoid, yet they have Data types with conflicting names defined in their respective modules. When you see the data type First, you cannot tell what someone is talking additional context. In general, base strives to avoid duplicate identifiers. The only other exception to this rule I can think of is that Bifunctor and Arrow both use the identifiers first and second. But, the situation with Data.Semigroup and Data.Monoid is higher impact since people are more likely to import these modules unqualified together.

(As an aside, and the confusion I’m talking about here isn’t entirely hypothetical. I got tripped up by this when I first started using the semigroups library. I had to train myself to stop importing Data.Monoid unqualified, because it kept stealing these identifiers)

Again, the two reasons are that these are no longer necessary and that they cause confusion. I would appreciate any feedback, including simple nods of agreement or disagreement. Thanks.
--
-Andrew Thaddeus Martin
Ivan Lazar Miljenovic
2018-04-12 00:17:29 UTC
Permalink
Post by Andrew Martin
I propose that the data types First and Last, provided by Data.Monoid, be marked deprecated in GHC 8.6 and removed in GHC 8.10. The Semigroup-Monoid Proposal (SMP) brought about changes that, I will argue, make these data types (1) unneeded and (2) confusing.
import qualified Data.Monoid as M
import qualified Data.Semigroup as S
M.First a === Maybe (M.First a)
M.Last a === Maybe (M.Last a)
Do you mean `M.First a === Maybe (S.First a)` (and similarly for Last)?

I'm +0.5 on this (more because of potential code churn.)

Since base-4.11 the Maybe instances also use Semigroup rather than
Monoid; is there a plan to deprecate the Option type as well?
--
Ivan Lazar Miljenovic
***@gmail.com
http://IvanMiljenovic.wordpress.com
Andrew Martin
2018-04-12 00:35:27 UTC
Permalink
Yes, I meant to say S.First and S.Last on the right-hand sides. I’m trying to get rid of Option on https://ghc.haskell.org/trac/ghc/ticket/15028. It will likely need to be discussed on the mailing list, but I figured I would just check on the trac first for that one since it’s more clear that Option is no longer useful.

Sent from my iPhone
Post by Ivan Lazar Miljenovic
Post by Andrew Martin
I propose that the data types First and Last, provided by Data.Monoid, be marked deprecated in GHC 8.6 and removed in GHC 8.10. The Semigroup-Monoid Proposal (SMP) brought about changes that, I will argue, make these data types (1) unneeded and (2) confusing.
import qualified Data.Monoid as M
import qualified Data.Semigroup as S
M.First a === Maybe (M.First a)
M.Last a === Maybe (M.Last a)
Do you mean `M.First a === Maybe (S.First a)` (and similarly for Last)?
I'm +0.5 on this (more because of potential code churn.)
Since base-4.11 the Maybe instances also use Semigroup rather than
Monoid; is there a plan to deprecate the Option type as well?
--
Ivan Lazar Miljenovic
http://IvanMiljenovic.wordpress.com
Mario Blažević
2018-04-12 04:57:57 UTC
Permalink
Post by Andrew Martin
I propose that the data types First and Last, provided by Data.Monoid, be marked deprecated in GHC 8.6 and removed in GHC 8.10. The Semigroup-Monoid Proposal (SMP) brought about changes that, I will argue, make these data types (1) unneeded and (2) confusing.
+1 from me.
Henning Thielemann
2018-04-12 07:12:00 UTC
Permalink
(As an aside, and the confusion I’m talking about here isn’t entirely
hypothetical. I got tripped up by this when I first started using the
semigroups library. I had to train myself to stop importing Data.Monoid
unqualified, because it kept stealing these identifiers)
Unqualified imports are not the problem - unqualified imports without
import list are the problem. People should not do that.
Andrew Martin
2018-04-12 11:23:56 UTC
Permalink
I agree somewhat. In the last two years, I've gotten more into the habit
about being explicit with import lists for commonly-used modules like
Control.Monad, Control.Applicative, and Data.Monoid. This is especially the
case when I'm writing library code (that I expect that other people may
read one day), although I'm more lax in application code. Still, it's nice
to be able to fire up GHCi and do something like this without having to
Post by Andrew Martin
:m Data.Monoid Data.Semigroup
But yes, in theory, people should avoid this. In practice, they often don't.

On Thu, Apr 12, 2018 at 3:12 AM, Henning Thielemann <
(As an aside, and the confusion I’m talking about here isn’t entirely
Post by Andrew Martin
hypothetical. I got tripped up by this when I first started using the
semigroups library. I had to train myself to stop importing Data.Monoid
unqualified, because it kept stealing these identifiers)
Unqualified imports are not the problem - unqualified imports without
import list are the problem. People should not do that.
--
-Andrew Thaddeus Martin
Elliot Cameron
2018-04-12 15:15:25 UTC
Permalink
+1 I've been bitten by this several times. This is especially confusing
when you are using Monoid in one module and you import a different module
that happens to use the Semigroup variants, and vice versa.
Post by Andrew Martin
I agree somewhat. In the last two years, I've gotten more into the habit
about being explicit with import lists for commonly-used modules like
Control.Monad, Control.Applicative, and Data.Monoid. This is especially the
case when I'm writing library code (that I expect that other people may
read one day), although I'm more lax in application code. Still, it's nice
to be able to fire up GHCi and do something like this without having to
Post by Andrew Martin
:m Data.Monoid Data.Semigroup
But yes, in theory, people should avoid this. In practice, they often don't.
On Thu, Apr 12, 2018 at 3:12 AM, Henning Thielemann <
(As an aside, and the confusion I’m talking about here isn’t entirely
Post by Andrew Martin
hypothetical. I got tripped up by this when I first started using the
semigroups library. I had to train myself to stop importing Data.Monoid
unqualified, because it kept stealing these identifiers)
Unqualified imports are not the problem - unqualified imports without
import list are the problem. People should not do that.
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Edward Kmett
2018-04-13 16:14:27 UTC
Permalink
I'm +1 on doing this in general.

However, the timing may need to be adjusted slightly in light of the
3-release policy, with which one could argue would indicate that the
deprecation warning shouldn't happen until 8.8, though the removal could
still happen in 8.10.

The issue there comes from the fact that we're just now getting Semigroup
as a superclass of Monoid, so if you want to write code compatible across 3
releases without warnings, for each range of 3 releases sliding over time,
as of 8.6 there'd be a window where you couldn't necessarily use
Semigroup.First/Last on 8.2 (the bottom edge of the window) in all
situations, but the deprecation warning would be screaming at you anyways.
An end-goal of being done with this by 8.10 fits nicely, though. Ironically
the 3-release policy makes this a bit worse as it'd allow us to straight up
remove it in 8.8 sans deprecation, but not warn in 8.6, so 8.10 with
deprecation in 8.8 seems a sensible choice.

The Option type can go through the same deprecation timing. It only existed
because of the old Monoid instance for Maybe.

-Edward
Post by Andrew Martin
I propose that the data types First and Last, provided by Data.Monoid, be
marked deprecated in GHC 8.6 and removed in GHC 8.10. The Semigroup-Monoid
Proposal (SMP) brought about changes that, I will argue, make these data
types (1) unneeded and (2) confusing.
Why are they no longer needed? Data.Semigroup provides two identically
named data types (First and Last). These have Semigroup instances matches
what their names suggest. Additionally, SMP corrects the Monoid instance
for Maybe so that it now lifts Semigroup instances instead of Monoid
import qualified Data.Monoid as M
import qualified Data.Semigroup as S
M.First a === Maybe (M.First a)
M.Last a === Maybe (M.Last a)
When I say "equivalence", I mean that their Monoid instances have the same
behavior. Their Show/Read instances are certainly different, and I’m not
sure about their Ord instances.
Getting back to the second reason, removing these data types would
eliminate confusion. It’s strange that Semigroup is a superclass of Monoid,
yet they have Data types with conflicting names defined in their respective
modules. When you see the data type First, you cannot tell what someone is
talking additional context. In general, base strives to avoid duplicate
identifiers. The only other exception to this rule I can think of is that
Bifunctor and Arrow both use the identifiers first and second. But, the
situation with Data.Semigroup and Data.Monoid is higher impact since
people are more likely to import these modules unqualified together.
(As an aside, and the confusion I’m talking about here isn’t entirely
hypothetical. I got tripped up by this when I first started using the
semigroups library. I had to train myself to stop importing Data.Monoid
unqualified, because it kept stealing these identifiers)
Again, the two reasons are that these are no longer necessary and that
they cause confusion. I would appreciate any feedback, including simple
nods of agreement or disagreement. Thanks.
--
-Andrew Thaddeus Martin
_______________________________________________
Libraries mailing list
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Loading...