[Haskell-cafe] some questions about Template Haskell

John Lato jwlato at gmail.com
Mon Jul 1 02:34:00 CEST 2013


On Mon, Jul 1, 2013 at 6:01 AM, TP <paratribulations at free.fr> wrote:

> oleg at okmij.org wrote:
>
> >> pr :: Name -> ExpQ
> >> pr n = [| putStrLn $ (nameBase n) ++ " = " ++ show $(varE n) |]
> >
> > The example is indeed problematic. Let's consider a simpler one:
> >
> >> foo :: Int -> ExpQ
> >> foo n = [|n + 1|]
> >
> > The function f, when applied to an Int (some bit pattern in a machine
> > register), produces _code_. It helps to think of the code
> > as a text string with the
> > source code. That text string cannot include the binary value that is
> > n. That binary value has to be converted to the numeric text string, and
> > inserted in the code. That conversion is called `lifting' (or
> > quoting). The function foo is accepted because Int is a liftable type,
> > the instance of Lift. And Name isn't.
>
> Thanks Oleg,
> Probably the following question will be stupid, but I ask it anyway: in my
> initial example, (nameBase n) returns a String, so we are not in the case
> where it is not "liftable"? In fact I am not sure to have understood your
> answer.
>

The problem isn't the output of nameBase, it's the input parameter 'n'.  In
your example, you've created a function that takes input (a Name) and
generates code based upon that input.  In order to lift a value (n) from an
ordinary context into a quote, it needs a Lift instance.


>
> Now, I have found another behavior difficult to understand for me:
>
> > runQ $ lift "u"
> ListE [LitE (CharL 'u')
> > runQ $ [| "u" |]
> LitE (StringL "u")
>
> So we have similar behaviors for lift and [||]. We can check it in a
> splice:
>
> > $( [| "u" |] )
> "u"
> > $( lift "u" )
> "u"
>
> But if I replace a working version:
>
> pr n = [| putStrLn ( $(lift( nameBase n ++ " = " )) ++ show $(varE n) ) |]
>
> by
>
> pr n = [| putStrLn ( $([| (nameBase n) ++ " = " |]) ++ show $(varE n) ) |]
>
> I again get the error
>

In the working version, 'n' appears inside a splice, whereas in the other n
is in a quote.  AFAIK any value can be used in a splice (provided it meets
the staging restrictions), whereas only Lift-able values can be used in a
quote.

Perhaps it helps if you think about what a quote does: it allows you to
write essentially a string of Haskell code that is converted into an AST.
 For this to work, the quote parser needs to know how to generate the AST
for an identifier.  Like much of Haskell, it's type-driven.  For
identifiers in scope from imports, TH simply generates a variable with the
correct name.  But for data, the parser needs a way to generate an AST
representation, which is what Lift is for.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130701/b9d09865/attachment.htm>


More information about the Haskell-Cafe mailing list