Quasiquoters accepting non-typechecking expressions

I was surprised to find out the expression quasiquoter [| |] accepts expressions that don’t typecheck, see the ghci interaction below :

λ> runQ [| \x -> head x : head x |]

LamE [VarP x_20] (InfixE (Just (AppE (VarE GHC.List.head) (VarE x_20))) (ConE GHC.Types.:) (Just (AppE (VarE GHC.List.head) (VarE x_20))))

Is there a way to restrict quasiquoters to erroring out when their argument doesn’t typecheck, or to get an AST from a later compiler stage, after typechecking?

My aim is : given the AST of a well-typed expression, produce new top-level declarations at compile time, e.g. Q [Dec] . Is this possible?

(I secretly hope @mpickering will appear and tell me I need to write a GHC source plugin. )

You could use a typed quotation.

e :: Quote m => Code m [a]
e = [|| \x -> head x : tail x ||]
exp :: IO Exp
exp = runQ (unTypeCode e)
4 Likes

Thank you! I had forgotten about those.