More informative error reporting from QuasiQuoters
Motivation
When a QuasiQuoter
fails (calling fail
), there are (essentially)
two potential reasons:
- There is something wrong with part or all of the string it is asked to interpret.
- There is something wrong with the context it occurs in.
GHC's error highlighter assumes the first reason. For example, suppose
defaultQuasiQuoter :: QuasiQuoter
defaultQuasiQuoter = QuasiQuoter
{ quoteExp = f "use in expression contexts."
, quotePat = f "use in pattern contexts."
, quoteType = f "use in types."
, quoteDec = f "creating declarations."
}
where
f m _ = fail $ "This quasiquoter is not for " ++ m
If I write
f [defaultQuasiQuoter| whatever |] = 3
I get the error
Vest.hs:6:12: error:
• This quasiquoter is not for use in pattern contexts.
• In the quasi-quotation: [myPatQQ| Whatever |]
|
6 | f [myPatQQ| Whatever |] = 3
| ^^^^^^^^^^^^
The error highlighting suggests that the problem is in Whatever
, but in fact it is not.
Proposal
It would be nice to have a mechanism by which the QuasiQuoter
can signal whether it's reporting an error with its argument or with its context. Where it's reporting an error with its argument, it would also be great if it could (optionally) indicate where in its argument string it encountered a problem. These argument strings can be extremely long, so just telling the user that the problem is "somewhere out that way" isn't very helpful. The options I can think of:
- Add appropriate methods to
Quasi
. This seems cleanest. - Use the fact that
Quasi
is a subclass ofMonadIO
, letting particular thrown exception types represent these situations. This is pretty hideous, and doesn't deal nicely with recoverable errors.