TP | 24 Aug 17:00 2013
Picon

Template Haskell: let statement in a splice put in the "main = do" part of a program?

Hi,

I continue to test Template Haskell, and I have some difficulties to use a 
splice $() in a "do" contained in the "main" part of a program. Here is an 
example. I want to make a splice that does `let a="a"` in my code.

$ cat MakeLetStatement.hs
----------------------------
{-# LANGUAGE TemplateHaskell #-}

module MakeLetStatement where

import Language.Haskell.TH

makeLetStatement :: String -> ExpQ
makeLetStatement s = return $ DoE $ [ LetS $ [ ValD (VarP $ mkName s)
                (NormalB $ LitE $ StringL s) [] ]]
----------------------------

$ cat test_MakeLetStatement.hs
----------------------------
{-# LANGUAGE TemplateHaskell #-}

import MakeLetStatement

main = do

$(makeLetStatement "a")
-- print a
----------------------------
(Continue reading)

Brandon Allbery | 24 Aug 18:03 2013
Picon

Re: Template Haskell: let statement in a splice put in the "main = do" part of a program?

On Sat, Aug 24, 2013 at 11:00 AM, TP <paratribulations <at> free.fr> wrote:
main = do

$(makeLetStatement "a")
-- print a

Is that the actual indentation you used? Because it's wrong if so, and the error you would get is the one you're reporting. Indentation matters in Haskell.

    In an equation for `main': main = do { $(makeLetStatement "a") }

You cannot *end* a do with a let-statement; it requires something else following it. You have nothing following it, as shown by the above fragment from the error message.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
TP | 24 Aug 18:36 2013
Picon

Re: Template Haskell: let statement in a splice put in the "main = do" part of a program?

Brandon Allbery wrote:

>> main = do
>>
>> $(makeLetStatement "a")
>> -- print a
>>
> 
> Is that the actual indentation you used? Because it's wrong if so, and the
> error you would get is the one you're reporting. Indentation matters in
> Haskell.

Yes, it matters, but not after "main = do": all the lines can start at the 
beginning of the line. Am I wrong? Or do I not understand what you say?

>     In an equation for `main': main = do { $(makeLetStatement "a") }
>>
> 
> You cannot *end* a do with a let-statement; it requires something else
> following it. You have nothing following it, as shown by the above
> fragment from the error message.

Yes, I have explained why: to be able to see the evaluation of the splice; 
otherwise I obtain "Not in scope: `a'" if I uncomment "-- print a" at the 
end of my code; I have explained everything in my initial post.

TP
adam vogt | 26 Aug 04:00 2013
Picon

Re: Template Haskell: let statement in a splice put in the "main = do" part of a program?

On Sat, Aug 24, 2013 at 11:00 AM, TP <paratribulations <at> free.fr> wrote:
> that has type Stmt, in an ExpQ that seems to be the only thing that we can
> put in a splice. I have found that it can only be done by doE (or DoE) and
> compE (or CompE) according to
>
> http://www.haskell.org/ghc/docs/latest/html/libraries/template-haskell-2.8.0.0/Language-Haskell-TH.html#v:doE
>
> But doE is not a solution as we have seen above, and compE is to construct
> list comprehensions, which is a different thing.
>
> So, is there any solution to my problem?

Hi TP,

TH quotes limited as you've noticed. One way to generate similar code
is to note that:

do
  let x = y
  z

is the same as let x = y in do z. You can generate the latter with
something like the following file, but the `a' isn't in scope for the
second argument to makeLetStatement. The uglier $(dyn "a") works,
though I suppose it's more verbose than manually in-lining the
variable a.

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH

main = $(let

    makeLetStatement :: String -> ExpQ -> ExpQ
    makeLetStatement s rest = letE [ valD (varP (mkName s))
                    (normalB $ stringE s) []]
                    rest

    in makeLetStatement "a" [| print $(dyn "a") |] )

--
Adam
TP | 27 Aug 23:36 2013
Picon

Re: Template Haskell: let statement in a splice put in the "main = do" part of a program?

adam vogt wrote:

> TH quotes limited as you've noticed. One way to generate similar code
> is to note that:
> 
> do
>   let x = y
>   z
> 
> is the same as let x = y in do z. You can generate the latter with
> something like the following file, but the `a' isn't in scope for the
> second argument to makeLetStatement. The uglier $(dyn "a") works,
> though I suppose it's more verbose than manually in-lining the
> variable a.
> 
> {-# LANGUAGE TemplateHaskell #-}
> import Language.Haskell.TH
> 
> main = $(let
> 
>     makeLetStatement :: String -> ExpQ -> ExpQ
>     makeLetStatement s rest = letE [ valD (varP (mkName s))
>                     (normalB $ stringE s) []]
>                     rest
> 
>     in makeLetStatement "a" [| print $(dyn "a") |] )

Thanks Adam.
Unfortunately, this solution is not satisfying because the goal is to put 
only one mention to "a" in the "main" part, putting all the repetitive code 
and ExpQ's in a separate module. Tonight, I've tried hard one more time 
without more success.
Maybe I have to stick to non-let expressions in the "main" part of a script, 
when it comes to TH. It should nevertheless allow me to call functions, make 
tests, etc.

Thanks,

TP

Gmane