
hi, I sent the message below to the template Haskell mailing list and it was suggested that I send it to the more general Haskell mailing list. After my question, I attached a few responses I have received. Thanks in advance for any suggestions. Dave ------------------------ I am new to Haskell and even more so to Haskell templates -- if there is an obvious answer to my question, please just point me at the relevant URL. Thanks! (If you think I should email this query to a broader Haskell mailing list let me know too.) My friends and I are thinking about adding an extension to Haskell to implement a variant of the PADS domain-specific language. PADS is a convenient syntax to describe a file format and generate a bunch of tools for it such as parser, printer, xml translator, semi-structured query engine, statistical profiler, etc. (We also have tools to automatically infer descriptions from example data but that's not quite the point here.) See www.padsproj.org/ for lots more info and examples of PADS for C and PADS for O'Caml. The bottom line question is I'm wondering if I can or should implement my PADS extension using Template Haskell to support the syntactic extensions. If not Template Haskell, is there another Haskell toolkit I should know about? If Template Haskell isn't powerful enough, I'll probably just write a standalone compiler that parses my special syntax and spits out a file full of Haskell declarations (this would be a slight shame because then I would probably not support writing PADS declarations in the midst of other Haskell code). I've looked at simple Template Haskell examples from the Haskell wiki, such as the printf example, but I need to introduce a lot more syntax than that ... What do I need from Template Haskell? Well what I would like to do is add a bit of syntax to Haskell that allows users to define what looks like non-standard type declarations. The "compiler" for these non-standard type declarations will generate a collection of ordinary Haskell declarations that can be used by a programmer. The non-standard typing declarations will be a mixture of what looks like Haskell type declarations, Haskell code, perl-style syntax for regular expressions and perhaps some other stuff I'm not thinking of right now. For example, suppose I want to write a program that converts a file that contains a list of friends into XML (it's a bit of an artificial example so I can illustrate several features): 3 Simon;Peyton Jones John;Launchbury #Phil;Wadler The format starts with a number on the first line to indicate the number of entries in the file. Each line contains one entry which is a first name then a ';' then a last name. Some lines begin with a # -- they are commented out because I'm no longer friends with them. Naturally, Phil Wadler falls into that category. :-) ! The Haskell program I want to write to do this would look something like: ------------------------- {| pdata Line = Comment /#.*/ | Name {first::Pstr /;/, last ::Pstr /\n/} ptype Friends = (x::Pint, |{ x > 0 }|, /\n/, PlistFW x) |} friendsToXML :: String -> XML friendsToXML s = PADSTools.toXML Friends s ------------------------- Notice the following syntactic features: -- {| and |} are delimiters that begin/end pads code (I don't really care what the delimiters are as long as they are relatively concise. For instance, if the delimiters were $( ... ), for instance, that would be fine. -- inside {| and |}, we can jump back into Haskell by using the delimiters |{ and |} -- there are some built-in, pre-defined base types like Pstr (for parsing and printing strings) and Pint (for parsing and printing integers), PlistFW (which takes an argument x to specify the number of elements in the list) -- regular expressions /..../ show up in the middle of what would otherwise be Haskell type declarations -- there is syntax for declaring datatype-like things (introduced by pdata keyword) -- the declarations are dependent types in that there is binding (eg: the x::Pint in the "Friends" type -- the x is bound here) -- variables bound in pads code can then be used in Haskell code nested inside the declaration (eg: the Haskell expression x > 0 refers to the variable x, defined in the outer pads code). -- the outer Haskell code refers to declarations made inside the PADS code. (eg: the Haskell function "friendsToXML s = PADS.Tools.toXML Friends s" refers to Friends, where Friends would be bound to a datastructure generated by the compiler for the pads code. PADSTools is a module defined a priori that contains a number of functions such as toXML, parse, print, query, etc.) Anyway, if you have any comments on how I should handle the syntactic extensions, let me know. Thanks again, Dave ------------ Ian: You can't create new syntax with TH; it's just Haskell (plus the TH syntactic extensions themselves, i.e. $( e ), and a few variants of [| e |]). You'd have to encode the info into Haskell syntax somehow, e.g. something like $( pdata "Line" [C "Comment" [], C "Name" [ ("first", ["Pstr", "/;"]), ... ) or parse them from strings (which isn't nice either, as Haskell doesn't have nice multi-line strings). Thanks Ian ----------------
From Claus Reinke:
well, how about using the new quasiquoting to get HereDocs:-) {-# LANGUAGE TemplateHaskell #-} module Here where import Language.Haskell.TH import Language.Haskell.TH.Quote here :: QuasiQuoter here = QuasiQuoter (litE . stringL) (litP . stringL) then {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} import Here s = [$here| hello multiline world |] test = lines s gives us *Main> test [" \r"," hello\r"," multiline\r"," world\r"," "] Claus ------------------
From Simon Peyton Jones:
Dave It's not clear to me a) whether or not you want new syntax (requires writing a parser) b) whether you want a single description to generate multiple different Haskell programs, or just one Concerning (a), as Claus says if you want special purpose syntax (ie not Haskell) then you need quasiquotation. This is only in the HEAD, not a released GHC, but it works reliably as far as I know. http://www.haskell.org/ghc/dist/current/docs/users_guide/template-haskell.ht... Concerning (b), if you want to write a program that generates one or more Haskell programs, then Template Haskell is good. But if you can get away with just one program, then you may not need that extra complexity. Many domain-specific languages embedded in Haskell use just Haskell (e.g. Parsec, Fran, Yampa...), not TH nor quasiquotation. You'd get a 30x wider audience on the Haskell Cafe mailing list, so yes, I'd try there too. Even jumping to Template Haskell as a solution may be premature; I'm not sure. Meanwhile perhaps other TH folk would like to join in? Simon
participants (1)
-
David Walker