RFC for a change in EmptyDataDecls instance deriving

Erik Hesselink hesselink at gmail.com
Wed Jul 15 17:55:16 UTC 2015


1) I think an empty case is nicer than the current error calls, since
it gives the (hopefully more informative) error from the point where
the empty data type was generated, instead of a generic error from the
instance. I've used similar instance definitions here [1].

2) It makes sense to me to also allow non-standalone deriving, and if
that is allowed, it should be the same as standalone deriving. Doing
anything else would be very confusing.

3) I have no idea. What's the rationale behind returning True when
comparing two Voids?

Erik

[1] https://github.com/silkapp/rest/blob/60faa55887fbf7332dc7aa82a9505e2d92f7c316/rest-types/src/Rest/Types/Void.hs

On Wed, Jul 15, 2015 at 5:56 PM, Ömer Sinan Ağacan <omeragacan at gmail.com> wrote:
> # RFC for a change in EmptyDataDecls instance deriving
>
> Hi all,
>
> There were some requests about EmptyDataDecls instance deriving and recently I
> made some progress towards implementing those. However as I implement things
> people started suggesting different behaviors than what I've implemented etc.
> In the end, we thought it'd be a good idea to ask libraries mailing list for
> which behavior to implement.
>
> # Summary
>
> Haskell 2010 doesn't support data types without any constructors(aka. empty
> data type)[1]. GHC supports it via EmptyDataDecls[2], but it fails to derive
> instances:
>
>     Decl.hs:3:18:
>         Can't make a derived instance of ‘Eq Z’:
>           ‘Z’ must have at least one data constructor
>           Possible fix: use a standalone deriving declaration instead
>         In the data declaration for ‘Z’
>
> Using StandaloneDeriving works, and it generates methods that calls `error`:
>
>     Derived instances:
>       instance GHC.Classes.Eq Main.Z where
>         (GHC.Classes.==) = GHC.Err.error "Void =="
>         (GHC.Classes./=) a_aCf b_aCg
>           = GHC.Classes.not ((GHC.Classes.==) a_aCf b_aCg)
>
> Note that these methods fail in first applications. So `(==) a` is an error, it
> doesn't need to be a fully saturated application.
>
> Ticket 7401[3] asks for a change in default deriving mechanism. I submitted a
> patch[4] that makes standard deriving work same as standalone deriving, for
> empty data types. This is completely backwards-compatible change, since
> previously deriving on empty data types wasn't working.(I also made some
> improvements on error messages)
>
> But then some people suggested that derived methods are not good, and we should
> use empty pattern match in method bodies instead[5]. E.g. if we derive Eq for
> an empty data type, generated instance should be:
>
>     instance Eq X where
>         a == b = case a of {}
>
> See [5] for motivation.
>
> So now we're also thinking about changing StandaloneDeriving for empty types
> too, to use empty pattern match instead of `error`.
>
> One thing to note is Data.Void.Void is doing completely different thing, it's
> Eq is defined like this:
>
>     instance Eq Void where
>         _ == _ = True
>
>
>
> So now that we have the story, my questions are:
>
> 1. What do you think is the right way to derive instances for empty data types?
>    An `error` or pattern match on bottom argument(e.g. empty case)?
>
> 2. Do you think with EmptyDataDecls and StandaloneDeriving, `deriving(..)` and
>    standalone deriving should derive same instances?
>
> 3. Should we change instances of Void on the way, for consistency? (Ord and Eq
>    especially)
>
>
>
> My answers:
>
> 1. Empty case. Users can always implement instances manually for always
>    succeeding (==) etc.
>
> 2. Definitely. Current deriving mechanisms are already complex and it's hard to
>    predict interactions between them(see [6]), I think we should do our best to
>    keep them as simple as possible. Personally I'd hate it if standalone
>    deriving and `deriving(...)` would implement different instances.
>
> 3. No opinion. May break some code? But making the change might be good for
>    consistency?
>
>
>
> If answers to (2) is yes, then we can just merge [4](which also improves error
> messages), but if we want to change how we define instances too, then it'll
> need some more work and I'll be working on that.
>
> In any case, I think we should update the user manual to specify what will be
> the derived instances. (as far as I can see currently it's not specified)
>
>
> ---
>
> [1]: https://www.haskell.org/onlinereport/haskell2010/haskellch11.html#x18-18200011
> [2]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/data-type-extensions.html#nullary-types
> [3]: https://ghc.haskell.org/trac/ghc/ticket/7401
> [4]: https://phabricator.haskell.org/D978
> [5]: https://ghc.haskell.org/trac/ghc/ticket/10577
>
> [6]: https://ghc.haskell.org/trac/ghc/ticket/10598
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


More information about the Libraries mailing list