[Haskell-cafe] [Template Haskell Question] On defining recursive templates.

Jonas Scholl anselm.scholl at tu-harburg.de
Wed Jan 20 19:13:44 UTC 2016


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Its not the compiler diverging, its your own code generating an infinite
expression.

[| zp |] is just a variable capturing the zp from the let expression.
The generated code looks like this:

let zp = \ y1 y2 y3 -> case (y1, y2, y3) of
    ((x1:xs1), (x2:xs2), (x3:xs3)) -> (x1, x2, x3) : zp xs1 xs2 xs3
    _ -> []
    in zp

You on the other hand call zipN from zipN', so the above expression is
inserted instead of zp. And in this expression there is again a zp,
which you replaced... and so on... so it looks like this:


\ y1 y2 y3 -> case (y1, y2, y3) of
    ((x1:xs1), (x2:xs2), (x3:xs3)) -> (x1, x2, x3) :
        (\ y1 y2 y3 -> case (y1, y2, y3) of
            ((x1:xs1), (x2:xs2), (x3:xs3)) -> (x1, x2, x3) :
                (\ y1 y2 y3 -> case (y1, y2, y3) of
                    ((x1:xs1), (x2:xs2), (x3:xs3)) -> (x1, x2, x3) :
(...) xs1 xs2 xs3
                    _ -> []) xs1 xs2 xs3
            _ -> []) xs1 xs2 xs3
    _ -> []

Hopefully it is now clear what is happening ; )

Jonas

On 01/20/2016 08:01 PM, Dominik Bollmann wrote:
> > Hello Haskellers, > > I'm currently diving into Template Haskell and
I just read the > original TH paper [1]. There they give the following
example of a > generic zip function: > > -- | A generic zip function.
Use (e.g.,) as $(zipN 3) xs ys zs. > zipN :: Int -> ExpQ > zipN n = [|
let zp = $(mkZip n [| zp |]) in zp |] > > -- | Helper function for zipN.
> mkZip :: Int -> ExpQ -> ExpQ > mkZip n contZip = lamE pYs (caseE (tupE
eYs) [m1, m2]) >   where >     (pXs, eXs)   = genPEs "x" n >     (pXSs,
eXSs) = genPEs "xs" n >     (pYs, eYs)   = genPEs "y" n >    
allCons      = tupP $ zipWith (\x xs -> [p| $x : $xs |]) pXs pXSs >    
m1           = match allCons continue []     >     m2           = match
wildP stop [] >     continue     = normalB [| $(tupE eXs) : $(appsE
(contZip:eXSs))|] >     stop         = normalB (conE '[]) > > -- |
Generates n pattern and expression variables. > genPEs :: String -> Int
-> ([PatQ], [ExpQ]) > genPEs x n = (pats, exps) >   where names        =
map (\k -> mkName $ x ++ show k) [1..n] >         (pats, exps) = (map
varP names, map varE names) > > This works as expected, e.g., `$(zipN 3)
[1..3] [4..6] [7..9]' gives > [(1,4,7),(2,5,8), (3,6,9)]. > > However, I
found this definition of passing `[| zp |]' as a helper > function
slightly confusing, so I tried to make it more succinct and to > call
zipN directly in the recursion: > > zipN' :: Int -> ExpQ > zipN' n =
lamE pYs (caseE (tupE eYs) [m1, m2]) >   where >     (pXs, eXs)   =
genPEs "x" n >     (pXSs, eXSs) = genPEs "xs" n >     (pYs, eYs)   =
genPEs "y" n >     allCons      = tupP $ zipWith (\x xs -> [p| $x : $xs
|]) pXs pXSs >     m1           = match allCons continue []     >    
m2           = match wildP stop [] >     continue     = normalB [|
$(tupE eXs) : $(appsE (zipN n:eXSs)) |] >     stop         = normalB
(conE '[]) > > This subtle change, however, causes the compiler to
diverge and to get > stuck at compiling splice `$(zipN' 3) [1..3] [4..6]
[7..9]'... > > Could anyone explain to me why the first approach works,
but the 2nd > small deviation does not? Is it because the compiler keeps
trying to > inline the recursive call to (zip N) into the template
indefinitely? > > Are there easier (more straightforward) alternative
implementations to > the (imo) slightly convoluted example of zipN from
the paper? > > Any hints are very much appreciated. > > Thanks, >
Dominik. > > [1]
http://research.microsoft.com/~simonpj/papers/meta-haskell/ >
_______________________________________________ > Haskell-Cafe mailing
list > Haskell-Cafe at haskell.org >
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAEBCAAGBQJWn9xYAAoJEM0PYZBmfhoBPT0IAJGgYDj2ISQheiA2OoTCB+k2
ELcbPWAlCFjpWqN4v2DUtTS1XSecJflvmusYyadGtW2s5OzBi1jOopwBFmB1KAz9
P8Lu4tM7OBbvlD5zQaIOD8rktOVtNrjT1r4mouu/dPPDgEF4ekVPkI4tphE3UD7Z
grYG6eRsRix6dnFX/Ee+0/EYQeANPsAXUZiEcBbkGVUR2jY44MoycilrH5gjwzTS
QSY2FZcAgeMqf1eBeYi3N3sMhCXH8zT2a2z+qzAVO6wMWTeXubXR6Hvk8naHf3Zv
ttIw1N1RXE2ncpOQLjnw3NmYY3wmlq4t/tltr1ubUKb0a/1PU/nx3Q+H4YIsz3g=
=v7H8
-----END PGP SIGNATURE-----




More information about the Haskell-Cafe mailing list