Reputation: 675
I'm building an eDSL on top of HaTeX. The problem I'm facing is that I want to display Haskell expressions in my LaTeX document and I want to use the same Haskell expression to help generate the document.
The obvious answer is to copy and paste the expression so that it appears both quoted and live. I want to avoid that because the expression is subject to change.
What I'm imagining is a quasi quoter that both splices its content as it stands and output a string that represents it.
For example, here is what I would like to type in:
document = do
title "this is an example document"
paragraph "This is normal text. We will now show the Haskell code that generates a table"
[quoted| makeTable ["heading1","heading2"] ["cell1","cell2"] |]
and I would like the quasi quote to expand to:
document = do
title "this is an example document"
paragraph "This is normal text. We will now show the Haskell code that generates a table"
makeTable ["heading1","heading2"] ["cell1","cell2"]
listing Haskell "makeTable [\"heading1\",\"heading2\"] [\"cell1\",\"cell2\"]"
For this, I need to write a QuasiQuoter:
quoted :: QuasiQuoter
quoted = QuasiQuoter
{ quoteExp = \str -> [e| $(_ str) >> listing Haskell $(lift str) |] }
I am unsure what to replace the hole with in $(_ str)
. I need to replace it with the Haskell expression quasi quoter but I am unsure how to call it. If e
was e :: QuasiQuoter
I could fill the hole with $(quoteExp e str)
but it unfortunately doesn't work. What should I fill it with?
Upvotes: 4
Views: 454
Reputation: 32309
Short answer: there is no easy way. This question is still was unanswered for a reason. String -> Q Exp
for Haskell is tough. The best way is probably through haskell-src-meta
which provides parsers which return Template Haskell AST. In particular the Language.Haskell.Meta.Parse
module gives us parseExp :: String -> Either String Exp
.
import Language.Haskell.Meta.Parse (parseExp)
quoted :: QuasiQuoter
quoted = QuasiQuoter
{ quoteExp = \str ->
case parseExp str of
Left msg -> fail "Could not parse expression."
Right exp -> [e| $(pure exp) >> listing Haskell $(liftString str) |] }
Upvotes: 5