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

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to