Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this Template Haskell work?

Consider this code:

magic :: String -> Q Exp
magic s = [e| putStrLn s |]

Now, as best as I can tell, this shouldn't actually work. Inside the Oxford brackets, s is not in scope. And yet, the above apparently works perfectly.

If we change this example slightly, it now breaks horribly:

magic :: Exp -> Q Exp
magic (VarE n) = [e| putStrLn (nameBase n) |]

Just like before, we have a variable not in scope. And this time, it breaks. But it doesn't complain about a variable not in scope; instead it whines about some undocumented class lacking an instance.

Anyone know what the heck is going on?

like image 581
MathematicalOrchid Avatar asked Dec 10 '22 02:12

MathematicalOrchid


1 Answers

s is in scope inside the Oxford brackets. Basically, you're allowed to use values of several types — those with Lift instances — inside the quoted expression, and they'll automatically be turned into the appropriate code to recreate the corresponding value on the other end.

For example, the Lift instance for Integers simply constructs the corresponding integer literal, while the instance for Maybe simply constructs the appropriate constructor applications. You can even define your own instances of Lift.

You're getting a "no instance" error because n is a Name, which isn't Liftable.

like image 195
ehird Avatar answered Dec 22 '22 16:12

ehird