[GHC] #7401: Can't derive instance for Eq when datatype has no constructor, while it is trivial do do so.

GHC ghc-devs at haskell.org
Tue May 10 20:26:32 UTC 2016


#7401: Can't derive instance for Eq when datatype has no constructor, while it is
trivial do do so.
-------------------------------------+-------------------------------------
        Reporter:  jpbernardy        |                Owner:
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  7.6.1
      Resolution:                    |             Keywords:  deriving,
                                     |  newcomer
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  GHC rejects       |  Unknown/Multiple
  valid program                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  Phab:D978
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by osa1):

 * owner:  osa1 =>


@@ -1,10 +1,34 @@
- On a "phantom datatype" D, one gets the message:
- {{{
- Can't make a derived instance of `Eq D':
-       `D' must have at least one data constructor
- }}}
- However there is a trivial, correct instance of Eq D:
- {{{
- instance Eq D where
-   (==) = undefined
- }}}
+ mpickering reminded me this ticket so before I leave the ownership of this
+ ticket let me write down the current status:
+
+ Basically there are a couple of things we can do and we just need someone
+ to
+ decide which one.
+
+ 1. Implement {{{==}}} as {{{_ == _ = True}}}. Pro: this is consistent with
+ {{{Void}}}'s {{{Eq}}} instance. Con: I think this lets some bugs to sneak
+ in. I think it doesn't make sense to compute things based on equality of
+ empty types, so at this point you've probably made a mistake and it's
+ better to just bail out.
+
+ 2. Implement {{{==}}} as `x == y = case x of {}`. Pro: it fixes the
+ problem with (1) and in a good way - you've probably used something like
+ {{{error "..."}}} for the empty type terms, so you get your error message.
+ Con: this inconsistent with {{{Void}}}.
+
+ 3. Leave this as is - no {{{deriving (Eq)}}}. This way we make the user
+ decide which behaviour to have. Pro: You can have whatever you want. Con:
+ Inconvenient.
+
+ These were also discussed at some point but IIRC most people agree that
+ these
+ are bad ideas:
+
+ 4. {{{x == y = error "(==) on empty type"}}}: If it's going to fail it's
+ better to fail like (2).
+
+ 5. {{{_ == _ = False}}}: Denotationally / type-theoretically bottoms are
+ equal or something like that? So it's better to implement (1) instead.
+
+ 6. Implement (2), change {{{Void}}}s instance too: Can potentially break
+ code.

New description:

 mpickering reminded me this ticket so before I leave the ownership of this
 ticket let me write down the current status:

 Basically there are a couple of things we can do and we just need someone
 to
 decide which one.

 1. Implement {{{==}}} as {{{_ == _ = True}}}. Pro: this is consistent with
 {{{Void}}}'s {{{Eq}}} instance. Con: I think this lets some bugs to sneak
 in. I think it doesn't make sense to compute things based on equality of
 empty types, so at this point you've probably made a mistake and it's
 better to just bail out.

 2. Implement {{{==}}} as `x == y = case x of {}`. Pro: it fixes the
 problem with (1) and in a good way - you've probably used something like
 {{{error "..."}}} for the empty type terms, so you get your error message.
 Con: this inconsistent with {{{Void}}}.

 3. Leave this as is - no {{{deriving (Eq)}}}. This way we make the user
 decide which behaviour to have. Pro: You can have whatever you want. Con:
 Inconvenient.

 These were also discussed at some point but IIRC most people agree that
 these
 are bad ideas:

 4. {{{x == y = error "(==) on empty type"}}}: If it's going to fail it's
 better to fail like (2).

 5. {{{_ == _ = False}}}: Denotationally / type-theoretically bottoms are
 equal or something like that? So it's better to implement (1) instead.

 6. Implement (2), change {{{Void}}}s instance too: Can potentially break
 code.

--

Comment:

 mpickering reminded me this ticket so before I leave the ownership of this
 ticket let me write down the current status:

 Basically there are a couple of things we can do and we just need someone
 to
 decide which one.

 1. Implement {{{==}}} as {{{_ == _ = True}}}. Pro: this is consistent with
 {{{Void}}}'s {{{Eq}}} instance. Con: I think this lets some bugs to sneak
 in. I think it doesn't make sense to compute things based on equality of
 empty types, so at this point you've probably made a mistake and it's
 better to just bail out.

 2. Implement {{{==}}} as {{{x == y = case x of {}}}}. Pro: it fixes the
 problem with (1) and in a good way - you've probably used something like
 {{{error "..."}}} for the empty type terms, so you get your error message.
 Con: this inconsistent with {{{Void}}}.

 3. Leave this as is - no {{{deriving (Eq)}}}. This way we make the user
 decide which behaviour to have. Pro: You can have whatever you want. Con:
 Inconvenient.

 These were also discussed at some point but IIRC most people agree that
 these
 are bad ideas:

 4. {{{x == y = error "(==) on empty type"}}}: If it's going to fail it's
 better to fail like (2).

 5. {{{_ == _ = False}}}: Denotationally / type-theoretically bottoms are
 equal or something like that? So it's better to implement (1) instead.

 6. Implement (2), change {{{Void}}}s instance too: Can potentially break
 code.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7401#comment:46>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list