Quasi quoting

Simon Peyton-Jones simonpj at microsoft.com
Mon Feb 1 01:50:42 EST 2010

Dear GHC users

This email is to announce two proposed changes to GHC's quasi-quotation mechanism.  For all I know, no one is using quasi-quotation (although it's a very cool feature, thanks to Geoff Mainland), but I didn't think I should take it for granted!

The current spec is here:

A quasi-quote can appear as a (a) expression (b) pattern, and looks like this
	[$pads| ...blah... |]

where 'pads' (of course any name will do) is a record of functions
   data QuasiQuoter = QuasiQuoter {
     quoteExp :: String -> Q Exp
     quotePat :: String -> Q Pat

The idea is that GHC evaluates (pads "...blah..."), and splices in the resulting Exp (or Pat) just as if that's what the user wrote in the first place.

Kathleen Fisher has started to use this for her PADS system, and came up with two suggestions.

1. Allow quasi-quotes at the (top-level) declaration level, just like TH splices. So you could say, at top level
	[$pads| ...blah... |]
and have it expand to a bunch of top level Haskell declarations. This seems like an unconditionally good idea. To support it we'd need to add a field to QuasiQuoter:
   data QuasiQuoter = QuasiQuoter {
     quoteExp :: String -> Q Exp
     quotePat :: String -> Q Pat
     quoteDec :: String -> Q [Dec]
but I don't think anyone will lose sleep over that.

2.  Make the notation less noisy for the "customer".  In particular, that '$' is scary, and redundant to boot.  She would like to write
	[pads| ...blah... |]

I can see the motivation here, but there are two reasons for caution. 
  (i) The Template Haskell quote forms [t| ... |] and [d| ... |] behave 
      rather differently.

  (ii) If "[pads|" is a lexeme, then some list comprehensions become illegal, such
       as  [x|x<-xs,y<-ys].  But note that because of Template Haskell quotations, 
       a comprehension [t|t<-ts] is already broken, and similarly with 'd', 'e'. 
       So the proposed change will make things *more* uniform, by grabbing every
       "[blah|" as lexeme. 

For me (i) is the main issue.  The differences are significant. 
  - A TH quote can appear only where an *expression* is expected
    But a quasiquote can be an expression or pattern or (assuming (1)) declaration

  - A TH quote has type (Q Typ) or (Q [Dec]) or (Q Exp)
    But a quasiquote is run immediately and spliced in place of the quote

  - A TH splice is run during type checking
    But a quasiquote is run during renaming

Even given all that, I'm strongly inclined to follow Kathleen's suggestion:
  - The differences are there all right, but in some ways the programmer thinks
    the same way:  [lang| blah |] switches to language 'lang'.

  - Many users will never encounter the issue; they'll just say 
	[pads| blah |]
    to wake up the PADS magic, and be oblivious to Template Haskell quotes

An alternative would be to have some other cue. Ones I've considered

  - $[pads| ...|], but allowing the $ to be omitted on top-level declarations, 
    top level, just as it now can for TH splices.  

  - [pads:| ... |], with the colon distinguishing quasi-quoting from TH.  

My gut feel is to go with [|pads| ... |].  Of course this'd be a change from the current syntax, but I think there are few enough users that they'll switch easily enough.

Any comments on any of this?


More information about the Glasgow-haskell-users mailing list