3

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!!!" |] }
user782220
  • 10,677
  • 21
  • 72
  • 135

1 Answers1

5

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." ....
user2407038
  • 14,400
  • 3
  • 29
  • 42
  • Oh so record syntax allows "incomplete" constructions in contrast to the typical data constructors allowed for the more common syntax for algebraic datatypes? Where in the documentation is this talked about in detail? – user782220 Dec 11 '13 at 03:37
  • Well, you can achieve the same semantics by just putting undefined in an ordinary constructor, eg Just undefined. – not my job Dec 11 '13 at 03:54
  • I actually can't find the documentation specifically on the traditional record syntax. Maybe it doesn't even exist; record syntax is really more of an afterthought in Haskell. In any case, it is just syntactic sugar; the datatype mentioned above will defined two functions `a :: D -> Int` and `b :: D -> Char`, as I'm sure you know. Record updates are just function application. And `D {a = 0}` is just equivalent to `D 0 (error "Missing field in record construction")`. – user2407038 Dec 11 '13 at 06:24