
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.pd... 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