Opened 6 years ago

Last modified 3 years ago

#7808 new feature request

data families and TH names do not mix well (e.g. cannot use TH deriving)

Reported by: duncan Owned by:
Priority: normal Milestone:
Component: Template Haskell Version: 7.6.2
Keywords: TypeFamilies Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


lots of Haskell libraries have TH functions like:

deriveJSON :: Name -> Q [Dec]

(e.g. aeson package for deriving JSON conversion)

They're used like

data Foo = Foo This That

$(deriveJSON ''Foo)

the deriveJSON reifies the Name and expects to find that the name refers to a data type, from which it finds the data constructors and generates the appropriate code.

Now, this doesn't work when the data type we want to derive an instance for is defined using a data family:

class FooClass a where
  data Foo a

instance FooClass Bar where
  data Foo Bar = Bar This That

$(deriveJSON ''Foo Bar) -- ???

We'd like to make the type Foo Bar an instance of the class (e.g. To/FromJSON) but deriveJSON expects a Name, and there is no name for this data type, its "name" is Foo Bar but obviously that's not a TH.Name.

Of course in general a name for a type application doesn't make sense, but for data family instances what other way do we have to refer to them?

Change History (7)

comment:1 Changed 6 years ago by igloo

difficulty: Unknown
Milestone: 7.8.1

comment:2 Changed 5 years ago by thoughtpolice


Moving to 7.10.1

comment:3 Changed 5 years ago by thoughtpolice


Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

comment:4 Changed 4 years ago by thoughtpolice


Milestone renamed

comment:5 Changed 4 years ago by thomie

Keywords: TypeFamilies added

comment:6 Changed 4 years ago by thomie

Milestone: 8.0.1

comment:7 Changed 3 years ago by RyanGlScott

Apologies for commenting on an extremely old Trac ticket.

The way I tackle this problem in libraries like bifunctors (see Data.Bifunctor.TH) is by allowing functions of the form :: Name -> Q a to take either a type constructor Name (for a plain datatype) or a data constructor Name (for a data family instance). The TH code is able to look up the original data family instance from any of its data constructor names, so it works, although it's a bit awkward. There's also the drawback that you can't do this trick for data family instances with no constructors... but how useful are those, really? :)

Note: See TracTickets for help on using tickets.