Backward-compatible role annotations

Dominique Devriese dominique.devriese at
Mon Mar 31 06:51:18 UTC 2014


(re-posting because I first used an address that is not subscribed to the lists)

I've been wondering about the following: it seems like the main
problem in this situation is that the GeneralizedNewtypeDeriving
extension changed meaning from "just coerce everything while deriving"
to "only coerce stuff if it's allowed by the relevant role
annotations".  Would it not be an alternative solution to split up the
GND extension into

* a backwards-compatible one (called GeneralizedNewtypeDeriving for
backwards compatibility ;)) that ignores role annotations (as before)
and uses unsafeCoerce whereever necessary
* a safe one (called e.g. SafeNewtypeDeriving) that respects role annotations

The first one could then be deprecated and removed in a release or
two. That might give library maintainers time to move their packages
to SafeNewtypeDeriving when they have tested that everything works...


P.S.: The above is based on a limited understanding of the problem, so
I'm sorry if it misses some aspect of the problem...

2014-03-31 2:14 GMT+02:00 Richard Eisenberg <eir at>:
> I spent some time thinking about what, precisely, can be done here to make
> folks happier. (See the thread beginning here:
> And, the
> answer seemed to all be in the concrete syntax. The only logical alternative
> (that I could think of) to having roles is to disallow GND, and I don't
> think anyone is proposing that. And, it is impossible to infer an author's
> desired roles for a datatype. The heuristics mentioned here all seem far too
> fragile and hard to predict to become a lasting feature of GHC (in my
> opinion). What's left? Concrete syntax.
> So, I have written and uploaded no-role-annots-1.0, a backward-compatible
> alternative to role annotations -- no CPP required. It's not as principled
> as proper role annotations, but it should do the job for most users.
> Here are two examples:
> 1. Datatypes:
>> import Language.Haskell.RoleAnnots
>> data Map k v =
>>   (Nominal k, Representational v) => MkMap [(k,v)]
> The constraints (which need be put on only one data constructor, if there
> are many) will get the built-in role inference mechanism to do what the user
> requests. In this example, the `Representational v` is actually redundant,
> but causes no harm. Because these classes have universal instances
> ("instance Nominal a") and have no methods, they should have no run-time
> significance. The only downside I can see is that the code above needs
> -XGADTs or -XExistentialQuantification to work, though it is neither a GADT
> nor has existentials. (Pattern-matching on such a definition needs no
> extensions.)
> 2. Newtypes:
> Newtype constructors cannot be constrained, unfortunately. So, we have to
> resort to Template Haskell:
>> import Language.Haskell.RoleAnnots
>> roleAnnot [NominalR, RepresentationalR]
>>   [d| newtype Map k v = MkMap [(k, v)] |]
> This is clearly worse, but I was able to come up with no other solution that
> worked for newtypes. Note that, in the example, I used the fact that
> Template Haskell interprets a bare top-level expression as a Template
> Haskell splice. We could also wrap that line in $( ... ) to be more explicit
> about the use of TH. Also problematic here is that the code above requires
> -XRoleAnnotations in GHC 7.8. To get this extension enabled without using
> CPP, put it in a condition chunk in your .cabal file, like this:
>> if impl(ghc >= 7.8)
>>   default-extensions: RoleAnnotations
> I hope this is helpful to everyone. Please feel free to post issues/pull
> requests to my github repo at
> Thanks,
> Richard
> _______________________________________________
> ghc-devs mailing list
> ghc-devs at

More information about the Libraries mailing list