Request for feedback: deriving strategies syntax

Ryan Scott at
Sun Jul 17 02:02:54 UTC 2016

I'm pursuing a fix to Trac #10598 [1], an issue in which GHC users do
not have fine-grained control over which strategy to use when deriving
an instance, especially when multiple extensions like
-XGeneralizedNewtypeDeriving and -XDeriveAnyClass are enabled
simultaneously. I have a working patch up at [2] which would fix the
issue, but there's still a lingering question of what the right syntax
is to use here. I want to make sure I get this right, so I'm
requesting input from the community.

To condense the conversation in [1], there are three means by which
you can derive an instance in GHC today:

1. -XGeneralizedNewtypeDeriving
2. -XDeriveAnyClass
3. GHC's builtin algorithms (which are used for deriving Eq, Show,
Functor, Generic, Data, etc.)

The problem is that it's sometimes hard to know which of the three
will kick in when you say `deriving C`. To resolve this ambiguity, I
want to introduce the -XDerivingStrategies extension, where a user can
explicitly request which of the above ways to derive an instance.

Here are some of the previously proposed syntaxes for this feature,
with their perceived pros and cons:

----- Pragmas
  * Examples:
      - newtype T a = T a deriving ({-# BUILTIN #-} Eq, {-# GND #-}
Ord, {-# DAC #-} Read, Show)
      - deriving {-# BUILTIN #-} instance Functor T
  * Pros:
      - Backwards compatible
      - Requires no changes to Template Haskell
  * Cons:
      - Unlike other pragmas, these ones can affect the semantics of a program
----- Type synonyms
  * Examples:
      - newtype T a = T a deriving (Builtin Eq, GND Ord, DAC Read, Show)
      - deriving instance Builtin (Functor T)
  * Pros:
      - Requires no Template Haskell or parser changes, just some
magic in the typechecker
      - Backwards compatible (back to GHC 7.6)
  * Cons:
      - Some developers objected to the idea of imbuing type synonyms
with magical properties
----- Multiple deriving clauses, plus new keywords
  * Examples:
      - newtype T a = T a
          deriving Show
          deriving builtin instance (Eq, Foldable)
          deriving newtype instance Ord
          deriving anyclass instance Read
      - deriving builtin instance Functor T
  * Pros:
      - Doesn't suffer from the same semantic issues as the other suggestions
      - (Arguably) the most straightforward-looking syntax
  * Cons:
      - Requires breaking changes to Template Haskell
      - Changes the parser and syntax significantly

Several GHC devs objected to the first two of the above suggestions in
[1], so I chose to implement the "Multiple deriving clauses, plus new
keywords" option in [2]. However, I'd appreciate further discussion on
the above options, which one you prefer, and if you have other
suggestions for syntax to use.

Ryan S.

More information about the ghc-devs mailing list