[Haskell-cafe] Template Haskell a Permanent solution?

Tillmann Rendel rendel at Mathematik.Uni-Marburg.de
Tue Dec 28 16:17:40 CET 2010


Hi,

Jonathan Geddes wrote:
> For TH use #1, compile-time parsing of arbitrary strings, I think it
> would be nice for quasiquote semantics to be modified so that code
> like
>
>> json :: String ->  JsonObject
>> json = ...
>>
>> data = [ json |
>>     { "name" : "Jonathan"
>>     , "favorite language": "Haskell"
>>     }
>> |]
>
> causes the function json to be called at compile time with a string
> argument of "   {\"name\" : \"Jonathan\"\n   , \"favorite language\":
> \"Haskell\"\n   }". The whole expression being then replaced with the
> result of the function application. What I like about this is that
> defining "quasiquoters" is trivial. They're just functions of the form
> String ->  a. Many such quasiquoters already exist and would be ready
> for use! I imagine certain rules would apply, ie a quasiquoter must be
> defined prior to use and in a separate module, etc.

First note that this is just quotation, not yet quasiquotation. For 
quasiquotation, you would also need to support antiquotation (i.e., the 
use of Haskell identifiers or even expressions in the middle of quoted 
syntax). And to reach something similar to the current support for 
quasiquotation, you would need to support patterns etc., too.


Secondly, I was going to propose to use generic programming to convert 
from a parser like (String -> JsonObject) to a quasiquoter for Json. But 
after half a day of experiments, I figured out that this idea is already 
developed in

   Geoffrey B. Mainland.
   Why It's Nice to be Quoted: Quasiquoting for Haskell.
   Haskell Workshop 2007

   Available at:
 
http://www.eecs.harvard.edu/~mainland/publications/mainland07quasiquoting.pdf

In that paper, Geoffrey Mainland explains how a parser can be 
generically upgraded to a quoter, reaching an intermediate conclusion on 
page 6:
> By using generic programming, we can take a parser and create
> expression and pattern quasiquoters for the language it parses with
> only four lines of code, including type signatures! This holds not
> just for our simple object language, but for any object language.

He goes on to explain how to add "support for antiquotation [...] with 
only slightly more than four lines of code".


The functions dataToExpQ and dataToPatQ from that paper are available in 
the TH library in Language.Haskell.TH.Quote. A simple helper function

   quasiQuoter :: Data a => (String -> Either String a) -> QuasiQuoter
   quasiQuoter parser = QuasiQuoter
     { quoteExp = either fail (dataToExpQ (const Nothing)) . parse
     , quotePat = either fail (dataToPatQ (const Nothing)) . parse
     }

should allow you to write your JSON example as follows:

   parse :: String -> Either String JsonObject
   parse = ...

   json = quasiQuoter parse

This seems simple enough to me, so it looks as if your use case is 
already supported as a library on top of the more general API.

   Tillmann



More information about the Haskell-Cafe mailing list