<div dir="ltr">lift and [| |] give similar results for that very stripped-down example, but it would be incorrect to extrapolate their behaviors from that case.  They&#39;re executed at different times, by different mechanisms, and have vastly different behavior.  It&#39;s also best to think of [| |] as having the type String -&gt; ExpQ, even though the input isn&#39;t syntactically quoted.<div>
<br></div><div style>Suppose you have a slightly different example:</div><div style><div><div><br></div><div>&gt; &gt; let x = 1 :: Int</div><div>&gt; &gt; runQ $ lift $ show x</div><div>&gt; ListE [LitE (CharL &#39;1&#39;)]</div>
<div>&gt; &gt; runQ [| show x |]</div><div>&gt; AppE (VarE GHC.Show.show) (VarE x_1627398832)</div></div><div><br></div><div style>With lift, the expression is evaluated, then the result &#39;1&#39; is lifted into an AST.  But TH quotes do something entirely different: they lift *the expression* into an AST.  In order to do so, the quoting mechanism needs to parse its input string, then determine what each identifier is referring to.</div>
<div style><br></div><div style>When you&#39;re defining a function:</div><div style><br></div><div style><div><div>&gt; &gt; let p :: (Show a, Lift a) =&gt; a -&gt; ExpQ; p n = [| show n |]</div></div><div><br></div><div style>
The quote has two terms: show and n.  &#39;n&#39; is a lambda-bound value, and show is free. Free variables are looked up in the environment.  That&#39;s why we see &#39;VarE GHC.Show.show&#39; in the AST above; the fully-qualified Name is generated and the AST references that name.  (numeric and string literals are represented directly)</div>
<div style><br></div><div style>This is the key difference between this function definition and running the splice above: in the function &#39;n&#39; is lambda-bound, whereas in the above splice &#39;x&#39; is a free variable.</div>
<div><br></div><div style>Lambda bindings can&#39;t be referenced by name because that name may not be in scope when the generated splice is run.  Instead, lambda-bound values must be lifted directly into the AST, which is exactly what &#39;lift&#39; does.  If we apply the function to a value, we can see the generated AST:</div>
<div style><br></div><div style><div>&gt; &gt; runQ (p 2)</div></div><div>AppE (VarE GHC.Show.show) (LitE (IntegerL 2))<br></div><div><br></div><div style>The generated AST has the number 2, and applies the function  GHC.Show.show to it.</div>
<div style><br></div><div style>If we want to show something that doesn&#39;t have a Lift instance, we can&#39;t do it directly.  However, we can do this:</div><div style><br></div><div style><div>&gt; &gt; let q :: Show a =&gt; a -&gt; ExpQ; q n = [| $(lift $ show n) |]</div>
<div>&gt; &gt; runQ (q 2)</div><div>&gt; ListE [LitE (CharL &#39;2&#39;)]</div><div><br></div><div style>Note the differences.  We no longer require that &#39;n&#39; has a Lift instance.  However, the actual value of &#39;n&#39; never appears in the AST!  Instead, we first show &#39;n&#39;, then lift in the resulting string.  The order of operations is changed too.  In the first case, the literal 2 is lifted into the AST via lift, and the generated splice will apply show to that number whenever the splice is run.  In the second case, (show 2) is evaluated first, then the result is lifted into the AST (again via lift), causing that string to be referenced within the splice.</div>
<div style><br></div><div style>HTH,</div><div style>John</div><div style><br></div><div style><br></div></div></div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jul 3, 2013 at 5:44 AM, TP <span dir="ltr">&lt;<a href="mailto:paratribulations@free.fr" target="_blank">paratribulations@free.fr</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">John Lato wrote:<br>
<br>
&gt;&gt; Now, I have found another behavior difficult to understand for me:<br>
&gt;&gt;<br>
&gt;&gt; &gt; runQ $ lift &quot;u&quot;<br>
&gt;&gt; ListE [LitE (CharL &#39;u&#39;)<br>
&gt;&gt; &gt; runQ $ [| &quot;u&quot; |]<br>
&gt;&gt; LitE (StringL &quot;u&quot;)<br>
&gt;&gt;<br>
&gt;&gt; So we have similar behaviors for lift and [||]. We can check it in a<br>
&gt;&gt; splice:<br>
&gt;&gt;<br>
&gt;&gt; &gt; $( [| &quot;u&quot; |] )<br>
&gt;&gt; &quot;u&quot;<br>
&gt;&gt; &gt; $( lift &quot;u&quot; )<br>
&gt;&gt; &quot;u&quot;<br>
&gt;&gt;<br>
&gt;&gt; But if I replace a working version:<br>
&gt;&gt;<br>
&gt;&gt; pr n = [| putStrLn ( $(lift( nameBase n ++ &quot; = &quot; )) ++ show $(varE n) )<br>
</div>&gt;&gt; |]   ----- case (i) -----<br>
<div class="im">&gt;&gt;<br>
&gt;&gt; by<br>
&gt;&gt;<br>
&gt;&gt; pr n = [| putStrLn ( $([| (nameBase n) ++ &quot; = &quot; |]) ++ show $(varE n) )<br>
</div>&gt;&gt; |]   ----- case (ii) -----<br>
<div class="im">&gt;&gt;<br>
&gt;&gt; I again get the error<br>
&gt;&gt;<br>
&gt;<br>
&gt; In the working version, &#39;n&#39; appears inside a splice, whereas in the other<br>
&gt; n<br>
&gt; is in a quote.  AFAIK any value can be used in a splice (provided it meets<br>
&gt; the staging restrictions), whereas only Lift-able values can be used in a<br>
&gt; quote.<br>
<br>
</div>If I take this as a granted axiom, then I can admit the behavior above<br>
(error in case (ii), whereas it is working in case (i)) because n is a<br>
(Name), and so is not instance of Lift. Thus we are compelled to use lift<br>
instead of [||] (although the behavior is about the same for both in simple<br>
examples, as shown in my example above for &quot;u&quot;).<br>
<br>
I do not understand the exact reason for that, but I can do without; and<br>
maybe it is better, because I am very probably not enough experienced to<br>
understand the details (and the reason is perhaps not trivial when I read<br>
Oleg who writes that what gives an error above in Haskell works in<br>
MetaOCaml).<br>
<br>
What is strange is that:<br>
* in the version using &quot;lift&quot;, the definition of lift asks for the output of<br>
(nameBase n) to be an instance of Lift, what is the case because it is a<br>
string (cf my previous post in this thread).<br>
* whereas in the second version, we ask for n, not (nameBase n), to be an<br>
instance of Lift.<br>
<br>
Anyway, if we admit your axiom as granted, then we can also admit that the<br>
following version does not work (version of my initial post):<br>
<div class="im"><br>
&gt;&gt; &gt;&gt; pr :: Name -&gt; ExpQ<br>
&gt;&gt; &gt;&gt; pr n = [| putStrLn $ (nameBase n) ++ &quot; = &quot; ++ show $(varE n) |]<br>
<br>
</div>Thanks,<br>
<div class="HOEnZb"><div class="h5"><br>
TP<br>
<br>
<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br></div>