[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