Opened 9 years ago

Last modified 17 months ago

#4222 new feature request

Template Haskell lets you reify supposedly-abstract data types

Reported by: simonpj Owned by:
Priority: low Milestone:
Component: Template Haskell Version: 6.12.3
Keywords: Cc: sergueyz@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


Serguey Zefirov writes (on Haskell cafe) "Data.Map.Map and Data.Set.Set are exported abstractly, without exposing knowledge about their internal structure.

I cannot directly create my own class instances for them because of that. But I found that I can write Template Haskell code that could do that - those data types could be reified just fine."

Good point. It's not quite clear what a better design should be. Haskell controls data abstraction by whether or not the constructors of the data type are exported. But they might be exported by the module that defined them, but not to "clients" of the data type. So the data type is abstract to some importers but concrete to others.

So when should TH let you reify the representation of a data type? Maybe it should let you do so iff

  • The data constructors of the data type are in scope (somehow) at the reification site

So, to take an example:

module Conc( T(..), Blah(..) ) where
  data T = T1 | T2 Blah
  data Blah = A | B

module Abs( T, Blah ) where
  import Conc

module ReifyA where
  import Abs

  foo = reify ''T

module ReifyC where
  import Conc

  foo = reify ''T

So the reify in would "see" the data constructors of T, but not the one in ReifyA.

But this approach raises related questions.

  • What if some, but not all, of T's data constructors are in scope?
  • What if the data constructors are all in scope, but some mention a type that is not in scope? For example, suppose type Blah is not in scope, but you reify T?
  • At the moment, when you reify a data type you get its Dec. But if T is abstract, what Dec can we give it? Just giving it an empty constructor list seems wrong; after all, it might really be a zero-constructor data type. I suspect we may want a richer data type for Info (ie what reify returns).

All these require design thinking. Does anyone want to lead that debate? Otherwise things will probably stay as they are.

I've labelled this as a feature request, although it is a kind of bug, because of this design component.

Change History (10)

comment:1 Changed 9 years ago by igloo

Milestone: 6.16.1

comment:2 Changed 8 years ago by igloo

Priority: normallow

comment:3 Changed 7 years ago by igloo


comment:4 Changed 5 years ago by thoughtpolice


Moving to 7.10.1.

comment:5 Changed 5 years ago by thomie

Component: CompilerTemplate Haskell
difficulty: Unknown

comment:6 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:7 Changed 4 years ago by thoughtpolice


Milestone renamed

comment:8 Changed 4 years ago by thomie

Milestone: 8.0.1

comment:9 Changed 17 months ago by mgsloan

IMHO being able to reify stuff like this is a feature not a bug. See, for example, the package.

One thing that comes to mind here is just making it a special variety of warning when TH references things that are not imported. This way things like the "true-name" package will still be possible, but will cause warnings that can be ignored if the user chooses to.

comment:10 Changed 17 months ago by RyanGlScott

Another possibility is to restrict what can be reified in the presence of the Safe language extension. To my knowledge, Template Haskell's ability to reify abstract names is precisely what makes TemplateHaskell imply Unsafe, so perhaps we could regain its safety by restricting what it can do in Safe Haskell.

I agree that I wouldn't want to remove the ability to reify abstract names altogether, since there are many situations where that comes in handy.

Note: See TracTickets for help on using tickets.