[Template-haskell] Some ideas

Josef Svenningsson josefs at cs.chalmers.se
Mon Apr 26 19:58:17 EDT 2004


Hi TH'ers,

This weekend I just wrote my first "Hello World" in TH. Meta programming
is great fun! While hacking away a number of ideas popped up in my head
about ways of extending TH to make it even cooler. I realise this is not
the first mail in that category, there seems to be an endless number of
things one could possibly add to TH. Anyway, read as far as you like, it's
a pretty long mail.


Derving
=======

Is would be nice to make the deriving mechanism programmable with
Template Haskell. The problem is when the typechecker finds a deriving
clause for something it doesn't recognise, where should it look? What
we need is a way to register presence of a new deriving gizmo to GHC,
a new language construct in Template Haskell. Let's call it
'addDeriving'. It would be something which could only be invoked on
the toplevel of a module. What type should it have? Well since it's a
language construct I don't know what return type it should have but
it's argument type should be something like this:
(String, Dec -> Q [Dec]).

The first argument is the name we refer to in the deriving clause. For
example ' ... deriving Fold'. Does it have to be upper case? I don't
know but I don't think so. The second argument tells GHC how the
deriving works. GHC supplies the data type declaration and gets a
bunch of declarations back.

Using this we could say (on the toplevel of a module):
addDeriving ("Fold", deriveFold)

Note that this would let us derive not only instances but new
functions or even new data types. Mega Awsome!

Splicing pragmas
===============

It would be nice to be able to splice in compiler pragmas. For example
if one writes a TH module for deriving folds and builds one would like
to generate rules pragmas so that GHC can fuse these functions when
they are used. Generating self-optimising code :).

Concretely one would add a constructor to the Dec data type. Something
like this:

data Dec = ...
     | PragmaD Pragma

data Pragma
     = RulePr String Phase [(String,Maybe Type)] Exp Exp
     | InlinePr String
     | NoInlinePr String
     | Specialize String Type

data Phase
     = Always
     | Upto Int
     | From Int

Perhaps the deprecated pragma also makes sense. The other pragmas
doesn't seem to make sense here. This is ofcourse very GHC specific
but so is TH.

>From Meta Haskell to Meta X
===========================

Template Meta Haskell is a language which is a very nice meta language
for Haskell. It has some really nice quotation syntax for creating
abstract Haskell syntax using Haskell's concrete syntax.

But we all know that Haskell is a great meta language for any language,
not just for itself. It is in fact what Haskell does best if you ask
me. So it would be nice if we could extend this quotation mechanism to
work for any language. Here's a proposal for doing more or less
that. It is very much inspired by a very similar functionality in
SML/NJ. See:
http://www.smlnj.org/doc/quote.html

The idea is this: we want to generalise the Oxford brackets
(i.e. [| |]) so that they are overloaded. Here's an example:

id :: ObjectLang a => a
id = [| \x -> x |]

Since we in general want to generate new names a better type would
perhaps be:

id :: ObjectLang a => Q a

The real advantage of having this is ofcourse when we use the splicing
mechanism inside the quotation. Like this:

mkLet :: ObjectLang a => a -> Q a
mkLet body = [| let x = $body in x |]

The tricky thing is how to handle this in the parser.

In SML/NJ they translate the quotation syntax to the following data type:

data Frag a = Quote String | AntiQuote a

According to this scheme Oxford brackets would be translated into
something of type [Frag a]. For example:
formula a = [| $a == > A |]
would be translated to
formula a = [Quote " ", AntiQuote a, Quote " ==> A "]

Fo far this is exactly SML/NJ modulo syntax and some names. My idea is
that we stick in a little parser function in front of the list. This
function should be appropriately overloaded. Say we add the following class:

class ObjectLang a where
  parseOL :: [Frag a] -> Q a

Then our example above would be translated into:
formula a = parseOL [Quote " ", AntiQuote a, Quote " ==> A "]

Jolly useful!

Adding this mechanism to TH will probably mess up the parser pretty
badly. But I still think it is worth thinking through. This extension
could be rather useful after all.

One thing to think of is what to do with other syntactic categories. In TH
we have [d| |] for declarations, [p| |] for patterns and so forth. Should
there be a fixed number of syntactic categories for all object languages?
Hopefully not but how would you lift the restriction?


A long mail. Thank you for reading it all to the end. I hope you got
something out of it. If you're either Simon PJ och Tim S then please
consider the implications of what I've suggested. It would be nice to
know if any of this makes sense/is doable.

Cheers and happy meta programming,

       /Josef


More information about the template-haskell mailing list