Opened 3 years ago

Last modified 12 months ago

#12457 new feature request

Deriving should be (more closely) integrated with other metaprogramming methods

Reported by: mpickering Owned by:
Priority: normal Milestone:
Component: Compiler Version: 8.0.1
Keywords: deriving Cc: RyanGlScott, goldfire, osa1
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: #15650 Differential Rev(s):
Wiki Page:

Description

It is unfortunate that if we want to (efficiently) derive a new type class then we have to bake the derivation logic into GHC itself. It seems desirable to be able to implement new deriving methods in libraries in some manner.

Ryan Scott says:

I think this would be a wonderful thing to have. Matthew Pickering (cc'd) has expressed a desire to have all the logic for the bespoke deriving strategies compartmentalized into a library that could easily be expanded on in the future to support more typeclasses in base. (Bifunctor, anyone?)

Unfortunately, each of the major players in today's Haskell metaprogramming scene that I'm aware of have some downfalls that make them unsuitable as deriving replacements:

  • Template Haskell: Not portable. Staging issues make it hard to use as a drop-in replacement for the deriving keyword
  • GHC generics: Can't express all the optimizations that the bespoke deriving algorithms perform. Unperformant.
  • Haskell preprocessors: Difficult to integrate in a typical GHC workflow. Probably wouldn't have all the metadata you'd need to be feature-complete with what deriving does today.

The way I see it, the whole deriving business as it currently stands today is a somewhat-grotesque-but-darn-useful hack that gets around the lack of a truly nice metaprogramming facility in Haskell. I'm holding out hope that the work in https://github.com/shayan-najd/NativeMetaprogramming makes things nicer soon, and then we can revisit this idea. Until then, -XDerivingStrategies provides a way to contain some of the madness of deriving after having many features tacked onto it in recent GHC releases.

Change History (9)

comment:1 Changed 3 years ago by mpickering

Richard comments:

  • Template Haskell: Not portable. Staging issues make it hard to use

as a drop-in replacement for the deriving keyword

I do not understand "not portable" here. Do you mean that some architectures don't support TH?

What staging issues?

I'm imagining here having deriving Blah be surface syntax that desugars into some TH splice. You keep the nice user-facing syntax, but make the deriving mechanism itself specified in TH code.

comment:2 Changed 3 years ago by mpickering

Cc: RyanGlScott goldfire added

comment:3 Changed 3 years ago by osa1

Cc: osa1 added

comment:4 Changed 3 years ago by goldfire

I'll also add: I think we'll need a better way of dealing with types than TH has now. But it's possible that clever reifys plus the new addModFinalizer behavior of #11832 will be enough.

comment:5 Changed 3 years ago by RyanGlScott

Some prior art we can draw on: Rust 1.15 has a "custom derive" feature that let's you derive any trait using its macro system: https://doc.rust-lang.org/book/procedural-macros.html.

comment:6 Changed 2 years ago by RyanGlScott

Keywords: deriving added

comment:7 Changed 17 months ago by mpickering

I think this is solved by DerivingVia?

comment:8 Changed 17 months ago by RyanGlScott

I suppose it depends on what you mean by "solved" :)

It's true that DerivingVia provides a much higher degree of configurability than other deriving strategies, but it falls short of some goals:

  • If one's goal is to have a equivalent of, say, deriving Ord that produces equally efficient code, then DerivingVia isn't up to the task. Ultimately, the closest you could get is by leveraging GHC.Generics under the hood, which isn't always going to produce as efficient of code as a non-generics–based Ord instance.
  • Speaking of which, combining GHC.Generics with DerivingVia will only get you so far. You wouldn't be able to use this approach to derive Bifunctor, for instance, since we only have the Generic and Generic1 classes for handling classes of kinds * -> Constraint and (k -> *) -> Constraint, respectively.
  • Ultimately, DerivingVia still relies on compiler magic. The original ambition here was to make deriving syntactic sugar for a Template Haskell splice so that the code underlying deriving could be expressed as a normal TH program. (That way, folks could extend it quite naturally.) There's still a long ways to go before that is possible.

I'm not sure if those are what you had in mind when opening this ticket, so if they're not, feel free to close this.

comment:9 Changed 12 months ago by RyanGlScott

Source plugins might offer one way forward here. See #15650.

Note: See TracTickets for help on using tickets.