
First off, the first code isn't doing exactly what you think; gen1 3, for example, generates the parse tree: "<<" ++ show 3 ++ ">>" You can improve this in the following way: gen1 i = let x = "<<" ++ show i ++ ">>" in [| x |] which generates (for gen1 3, again) ['<', '<', '3', '>', '>'] Alternatively, you can generate the expression directly: gen1 i = LitE $ StringE $ "<<" ++ show i ++ ">>" which gives you exactly the parse tree "<<3>>". Now, the compiler will definitely treat the last two the same, but I'm not sure it will constant-fold "show 3" into "3" in your case. The "runQ" trick is really useful; in ghci; just use runQ with the code that you want to generate:
:set -fth :m +Language.Haskell.TH runQ [| "<<42>><<66>>" |] LitE (StringL "<<42>><<66>>")
You then just need to figure out how to make that object from the
inputs you have.
Also, here's something simple to try:
appendStrQ :: [ExpQ] -> ExpQ
appendStrQ = foldr (\x rest -> [| $(x) ++ $(rest) |]) [| "" |]
gen2 = appendStrQ . map gen1
-- ryan
On Wed, Mar 19, 2008 at 5:17 AM, Lars Oppermann
Hi all,
I am trying to get familiar with template haskell and I'm wondering whether the following is possible and if so, how it would be done properly...
I have two templates, and I'd like to use one from the other. For instance the first one might be
gen1 :: Int -> ExpQ gen1 i = [| "<<" ++ (show i) ++ ">>" |]
Thus, I gould do
$(gen1 42)
and I'd get "<<42>>"
now I'd like to use gen2 in another generated expression so that I could so
$(gen2 [42, 66])
and get "<<42>><<66>>"
My naive intention was to write
gen2 :: [Int] -> ExpQ gen2 is = [| map (\x -> $(gen1 x)) is |]
which gives me "Stage error: `x' is bound at stage 2 but used at stage 1
So I guess my actual question would be: how do I pass a variable bound outside a quotation into another splice used in that quotation?
Bests, Lars _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe