[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