Search code examples
haskelltemplate-haskell

Record syntax for QuasiQuoter constructor


The documentation for template Haskell says that QuasiQuoter is defined as

data QuasiQuoter = QuasiQuoter { quoteExp  :: String -> Q Exp,
                                 quotePat  :: String -> Q Pat,
                                 quoteType :: String -> Q Type,
                                 quoteDec  :: String -> Q [Dec] }

I have encountered examples such as silly shown below. How do they work given that they don't seem to fill in quotePat, quoteType, and quoteDec fields?

silly :: QuasiQuoter
silly = QuasiQuoter { quoteExp = \_ -> [| "yeah!!!" |] }

Solution

  • The answer has nothing to do with TH: if you don't initialize a field of a record constructor, trying to access that field will cause an error:

    >data D = D {a :: Int, b :: Char} deriving Show
    >D {a = 0}
    D {a = 0, b = *** Exception: <interactive>:26:1-9: Missing field in record construction :Interactive.b
    

    In this case, this is desired behavior since certain quoters only make sense in a certain context, and should throw an error if they are used improperly. Although, you would most likely want to provide more descriptive error message for your quoters, like so:

    quote = QuasiQuoter { 
       quoteExp = something, 
       quotePat = error "quote: Invalid application in pattern context." ....