Backward-compatible role annotations
Richard Eisenberg
eir at cis.upenn.edu
Mon Mar 31 00:14:55 UTC 2014
I spent some time thinking about what, precisely, can be done here to make folks happier. (See the thread beginning here: http://www.haskell.org/pipermail/libraries/2014-March/022321.html) 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 github.com/goldfirere/no-role-annots.
Thanks,
Richard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/ghc-devs/attachments/20140330/a88a79b8/attachment.html>
More information about the ghc-devs
mailing list