1

I'm trying to write a quasiquoter for some type declarations.

I've written something along the lines of

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH as TH
import Language.Haskell.TH.Quote

sample :: QuasiQuoter
sample =
   let tName    = TH.mkName "GenType"
       conName  = TH.mkName "GetType"
       nameName = TH.mkName "name"
       creator _ = return [TH.DataD [] tName [] [TH.RecC conName [(nameName, TH.NotStrict,TH.ConT ''String)]] [''Show, ''Eq]]
   in QuasiQuoter { quoteDec = creator
                  , quotePat = undefined
                  , quoteType = undefined
                  , quoteExp = undefined }

Now I have the issue of trying to make that type "GenType" available. I've taken a look at the yesod source code (where they do routes), but it's a little opaque for me. How does one make a type available from a quasiquoter?

Cactus
  • 27,075
  • 9
  • 69
  • 149
Khanzor
  • 4,830
  • 3
  • 25
  • 41

1 Answers1

3

Import your module into another one that has the QuasiQuotes LANGUAGE pragma turned on , and then use the syntax [sample||] to call it. Note that it needs to be in a separate module; you can't start using [sample||] in the same module as it is defined in. See e.g. section 7.17.1 in the GHC 7.10.1 manual:

Inside a splice you can only call functions defined in imported modules, not functions defined elsewhere in the same module.

So putting it all together, here's an example of using sample:

{-# LANGUAGE QuasiQuotes #-}
import SO_30447244_Def -- this is the module containing the code 
                       -- from the original question

[sample||]

foo :: GenType
foo = GetType "foo"
Cactus
  • 27,075
  • 9
  • 69
  • 149
  • Right, I just leave as a top level declaration. That actually makes sense - I was trying to load it from GHCi! – Khanzor May 27 '15 at 01:54
  • You can run it from GHCi to see (TH's internal representation of) the generated code by loading `SO_30447244_Def` and then running `runQ $ quoteDec sample ""`. – Cactus May 27 '15 at 02:41