Add default QuasiQuoter(s)
Motivation
Language.Haskell.TH.Quote gives us
data QuasiQuoter = QuasiQuoter {
-- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
quoteExp :: String -> Q Exp,
-- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
quotePat :: String -> Q Pat,
-- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
quoteType :: String -> Q Type,
-- | Quasi-quoter for declarations, invoked by top-level quotes
quoteDec :: String -> Q [Dec]
}
The documentation suggests that
if you are only interested in defining a quasiquoter to be used for expressions, you would define a 'QuasiQuoter' with only 'quoteExp', and leave the other fields stubbed out with errors.
This is not ideal. There are a few problems:
The easiest path, which some packages take, is to write something like
myqq = QuasiQuoter
{ quoteExp = ... }
The error message produced when myqq is used in the wrong context will not explain the problem at all; it'll just point out that there was an exception in Template Haskell code. The second problem is that using error, even more informatively, will produce an overly verbose, poorly formatted message because GHC assumes that it represents a bug in the quasiquoter. The correct thing is instead to use fail as usual.
Proposal
I suggest offering one or perhaps a couple of suitable "default" QuasiQuoter definitions. These could look like so:
defaultQuasiQuoter :: QuasiQuoter
defaultQuasiQuoter = QuasiQuoter
{ quoteExp = \_ -> fail "This quasiquoter is not for use in expressions"
, quoteType = \_ -> fail "This quasiquoter is not for use in types"
, quotePat = \_ -> fail "This quasiquoter is not for use in patterns"
, quoteDec = \_ -> fail "This quasiquoter is not for producing declarations"
}
namedDefaultQuasiQuoter :: String -> QuasiQuoter
namedDefaultQuasiQuoter n = QuasiQuoter
{ quoteExp = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for use in expressions"
, quoteType = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for use in types"
, quotePat = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for use in patterns"
, quoteDec = \_ -> fail $ "The " ++ n ++ " quasiquoter is not for producing declarations"
}
Now users can write things like
myqq = (namedDefaultQuasiQuoter "myqq")
{ quoteExp = ... }
The documentation should also indicate that the unused fields should fail rather than error.