Template Haskell Tutorial

Download Template Haskell Tutorial

Post on 10-May-2015

7.811 views

Category:

Technology

0 download

Embed Size (px)

TRANSCRIPT

<ul><li>1.Template Haskell Tutorialshort, illustrated examples from Illustrated Haskell </li></ul> <p>2. Motivating examplefst(x,_)= xfst3(x,_,_) = xfst4(x,_,_,_) = xprint $ fst3 ("hello world", 1, 2)print $ fst4 ("hello world", 1, 2, 3)So repetitive!Illustrated Haskell 3. Template Haskell to the rescue!Usage:{-# LANGUAGE TemplateHaskell #-}print $ $(fstN 3) ("hello world", 1, 2)print $ $(fstN 4) ("hello world", 1, 2, 3)Illustrated Haskell 4. How to write it?-- FstN.hs{-# LANGUAGE TemplateHaskell #-}module FstN whereimport Language.Haskell.THfstN :: Q ExpfstN n = dox &gt; char &gt;return $ Tag tagName childrenIllustrated Haskell 14. A simple test for our parser$ ghci HTML.hs&gt; parseTest tagNode "Hello, TH world!"Tag "html" [Text "Hello, ",Tag "strong" [Text "TH"],Text " world!]It works!Illustrated Haskell 15. Now we can write our QuasiQuoter-- HTML.hs The QuasiQuoter takes 4Html :: QuasiQuoterparameters. Each will be called when the quasi quoteHtml = QuasiQuoter is being invoked to create:htmlExpr An expressionundefined foo = [html| ... |] A pattern (for patternundefined matching)undefined bar [html| ... |] = 3 A type A top-level declarationhtmlExpr :: String -&gt; Q ExphtmlExpr = undefined We will do expression and pattern in this example For more information consult GHCs documentation Illustrated Haskell 16. htmlExpr is supposed to parse the contents within [html| |] and give back an ExphtmlExpr :: String -&gt; Q ExphtmlExpr str = do filename undefinedRight tag -&gt; [| tag |]As easy as that, loc_filename and location will giveus the filename of the user.Illustrated Haskell 17. Lets compile it!$ ghc HTML.hsError: No instance for (Lift Node) arising fromarising of `tagWhat is that? Well maybe we can satisfy it byimplementing the Lift instance for Node, asinstructed:instance Lift Node wherelift (Text t) = [| Text t |] lift (Tag name children) = [| Tag name children |]Illustrated Haskell 18. Lets try it out-- HTMLTest.hs{-# LANGUAGE TemplateHaskell , QuasiQuotes #-}import HTMLmain = print [html|Hello, THworld!|]$ ghci HTMLTest.hs&gt; mainTag "html" [Text "Hello, ",Tag "strong" [Text "TH"],Text" world!"]It works!Illustrated Haskell 19. Quasi quoting for patternsNow lets try to do some operations on our HTML structureIn this example we will convert an HTML tree into MarkdownMarkdown is a simple wiki syntax Example Markdown:Lets **rock** and _roll_! Corresponding HTML:Lets rock and rollUsually people convert Markdown to HTML. We will do itthe other way here.Illustrated Haskell 20. Lets make a simple converter-- HTMLTest.hsmarkdown (Tag "strong" children) ="**" ++ concatMap markdown children ++ "**"markdown (Tag "em" children) ="_" ++ concatMap markdown children ++ "_"markdown (Tag _ children)=concatMap markdown childrenmarkdown (Text t)=tThats some normal Haskell. For fun, were going to turn it into:-- HTMLTest.hsmarkdown [html||] = "**" ++ concatMap markdown children ++ "**"markdown [html||] = "_" ++ concatMap markdown children ++ "_"markdown [html||]= concatMap markdown childrenmarkdown [html|#text|]= textAre we gaining anything? Honestly not much. But well do it for the sake of an TH example.Illustrated Haskell 21. Add a pattern parser to our QuasiQuoter -- HTML.hs html :: QuasiQuoter html = QuasiQuoter htmlExpr htmlPat undefined undefined htmlPat:: String -&gt;Q Pat htmlPat""=[p| Tag _ children |] htmlPat"#text"=[p| Text text |] htmlPat( runQ [p| Tag "strong" chlidren |]ConP HTML.Tag [ LitP (StringL "strong"), VarP chlidren]So there we have almost had it.We just need to use Name at appropriate places and follow the types:htmlPat (</p>