[Template Haskell]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[Template Haskell]

Dominik Bollmann

Hi all,

I'm just getting my feet wet with template haskell, and I tried to write
 a tmap function which maps a function over the ith component of an
 n-tuple (which uses a slightly different approach than the given
 version on the TH wiki):
 
-- | Selects the ith component of an n-tuple
tsel :: Int -> Int -> ExpQ -- n-tuple a -> a
tsel i n = [| \t -> $(caseE [| t |] [alt]) |]
  where alt  = match (tupP pats) body []
        pats = map varP xs
        xs   = [ mkName ("x" ++ show k) | k <- [1..n] ]
        body = normalB . varE $ xs !! (i-1)

-- | Maps a function over the ith component of an n-tuple
tmap :: Int -> Int -> ExpQ -- :: (a -> b) -> n-tuple -> n-tuple
tmap i n = do
  f <- newName "f"
  t <- newName "t"
  lamE [varP f, varP t] $ [|
     let prefix    = map extract [1..(i-1)]
         new       = $f ($(tsel i n) $t)
         suffix    = map extract [(i+1)..n]
         extract k = $(tsel k n) t
     in tupE $ prefix ++ [new] ++ suffix |]

However, this code results in the following error:

Sandbox.hs:26:29: Stage error: ‘k’ is bound at stage 2 but used at stage 1 …
    In the splice: $(tsel k n)
    In the Template Haskell quotation
      [| let
           prefix = map extract [1 .. (i - 1)]
           new = $f ($(tsel i n) ($t))
           suffix = map extract [(i + 1) .. n]
           extract k = $(tsel k n) $t
         in tupE $ prefix ++ [new] ++ suffix |]
Compilation failed.

Could anyone explain to me what stage 2 and stage 1 refer to, and
further, what the logical flaw in the above snippet is? What exactly is
wrong with line `extract k = $(tsel k n) $t' ?

Thanks!

Dominik.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: [Template Haskell]

Michael Sloan
Hi!

The issue is that "extract k = ..." is a binding of k which will be present in the generated code (and so will be available at runtime).  The anti-quote $(tsel k n) cannot depend on k, because it gets run at compiletime.

Seems to me like that error message could use some improvement.  Why not something more like "Stage error: `k' is bound in generated code but used in compiletime code"?  AFAIK there is no such thing as stage 3 or stage 0, so the numbering seems a bit arbitrary.

-Michael

On Mon, Jan 25, 2016 at 2:58 AM, Dominik Bollmann <[hidden email]> wrote:

Hi all,

I'm just getting my feet wet with template haskell, and I tried to write
 a tmap function which maps a function over the ith component of an
 n-tuple (which uses a slightly different approach than the given
 version on the TH wiki):

-- | Selects the ith component of an n-tuple
tsel :: Int -> Int -> ExpQ -- n-tuple a -> a
tsel i n = [| \t -> $(caseE [| t |] [alt]) |]
  where alt  = match (tupP pats) body []
        pats = map varP xs
        xs   = [ mkName ("x" ++ show k) | k <- [1..n] ]
        body = normalB . varE $ xs !! (i-1)

-- | Maps a function over the ith component of an n-tuple
tmap :: Int -> Int -> ExpQ -- :: (a -> b) -> n-tuple -> n-tuple
tmap i n = do
  f <- newName "f"
  t <- newName "t"
  lamE [varP f, varP t] $ [|
     let prefix    = map extract [1..(i-1)]
         new       = $f ($(tsel i n) $t)
         suffix    = map extract [(i+1)..n]
         extract k = $(tsel k n) t
     in tupE $ prefix ++ [new] ++ suffix |]

However, this code results in the following error:

Sandbox.hs:26:29: Stage error: ‘k’ is bound at stage 2 but used at stage 1 …
    In the splice: $(tsel k n)
    In the Template Haskell quotation
      [| let
           prefix = map extract [1 .. (i - 1)]
           new = $f ($(tsel i n) ($t))
           suffix = map extract [(i + 1) .. n]
           extract k = $(tsel k n) $t
         in tupE $ prefix ++ [new] ++ suffix |]
Compilation failed.

Could anyone explain to me what stage 2 and stage 1 refer to, and
further, what the logical flaw in the above snippet is? What exactly is
wrong with line `extract k = $(tsel k n) $t' ?

Thanks!

Dominik.
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe