Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#10716 closed feature request (fixed)

Metadata in GHC.Generic should give access to strictness annotation

Reported by: StefanWehr Owned by:
Priority: normal Milestone: 8.0.1
Component: Compiler Version: 7.10.2
Keywords: Generics Cc: adamgundry, kosmikus, goldfire
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:1646
Wiki Page:


Currently, the metadata in the GHC.Generics module do not give access to the strictness annotations attached to a field of a datatype. It would be great if this piece of information could be added.

Background: we are using a class FullyStrict for ensuring that a datatype is fully strict (in the sense that all fields have bang patterns and the types of all fields are also fully strict). Currently we are using TemplateHaskell to derive the instances automatically. The TemplateHaskell function also checks that all fields have bang patterns.

To improve compilation speed, I would like to derive the instances with DeriveGeneric. But this is not possible because then I cannot implement the check whether all fields have bang patterns.

Change History (9)

comment:1 Changed 4 years ago by simonpj

Cc: adamgundry kosmikus goldfire added

I'm all for it. Would you like to describe the design as seen by a user; and maybe offer a patch? Adding Andres to cc.

comment:2 Changed 4 years ago by StefanWehr

Extended API

A new class is added to GHC.Generics:

class StrictSelector s

This class has no methods; it only serves as a type-level constraint for a selector having a bang pattern.

Also, I suggest changing the NoSelector type from GHC.Generics to accept a new type parameter:

data NoSelector t 

The new type parameter is either NoStrict or Strict. These two types are also added to GHC.Generics:

data NoStrict
data Strict

For anonymous selectors, we define an instance for StrictSelector:

instance StrictSelector (NoSelector Strict)

So far, this encodes strictness of a selector on the type-level. To access this information on the value-level, I suggest adding a new method to the type class Selector from GHC.Generics:

class Selector s where
    selName :: t s (f :: * -> *) a -> [Char]
    selIsStrict :: t s (f :: * -> *) a -> Bool -- NEW

My API proposal is not backwards compatible: the change to NoSelector will definitely break existing code, the addition of a new type class and two new data types might break existing code if the names are already used for something different. I tried avoiding the change to NoSelector but couldn't come up with a solution that brings the strictness (or lazyness) of a selector to the type-level. (For the application I have in mind, it's not enough to have these information on the value-level only.)

Changes to the deriving mechanism

The deriving mechanism for generics is extended in the following way:

  • replace occurrences of NoSelector with NoSelector Strict or NoSelector NoStrict
  • for named selectors carrying a bang pattern, generate an instance of StrictSelector T, where T is the type generated for the selector.

I'm happy to provide a patch for this, but first I want to make sure that my design is reasonable. Any comments?

comment:3 Changed 4 years ago by dreixel

Why can't we just add the selIsStrict part?

To get the information at the type level we better do it for all meta-data at the same time, and we can get it when we make GHC.Generics use DataKinds, as described in

comment:4 Changed 4 years ago by RyanGlScott

Differential Rev(s): Phab:1646
Status: newpatch

I've submitted Phab:D1646, which implements this idea. I included a sketch of my ideas in this wiki page.

comment:5 Changed 4 years ago by Ben Gamari <ben@…>

In ee6fba89/ghc:

Encode strictness in GHC generics metadata

This augments `MetaSel` with a `Bang` field, which gives generic
programmers access to the following information about each field

* `SourceUnpackedness`: whether a field was marked `{-# NOUNPACK #-}`,
  `{-# UNPACK #-}`, or not
* `SourceStrictness`: whether a field was given a strictness (`!`) or
  laziness (`~`) annotation
* `DecidedStrictness`: what strictness GHC infers for a field during
  compilation, which may be influenced by optimization levels,
  `-XStrictData`, `-funbox-strict-fields`, etc.

Unlike in Phab:D1603, generics does not grant a programmer the ability
to "splice" in metadata, so there is no issue including
`DecidedStrictness` with `Bang` (whereas in Template Haskell, it had to
be split off).

One consequence of this is that `MetaNoSel` had to be removed, since it
became redundant. The `NoSelector` empty data type was also removed for
similar reasons.

Fixes #10716.

Test Plan: ./validate

Reviewers: dreixel, goldfire, kosmikus, austin, hvr, bgamari

Reviewed By: bgamari

Subscribers: thomie

Differential Revision:

GHC Trac Issues: #10716

comment:6 Changed 4 years ago by bgamari

Resolution: fixed
Status: patchclosed

comment:7 Changed 4 years ago by StefanWehr

This is great news!

comment:8 Changed 4 years ago by simonpj

Keywords: Generics added

comment:9 Changed 4 years ago by thomie

Milestone: 8.0.1
Note: See TracTickets for help on using tickets.