A bug in the latest hsx or haskell-src-exts?

3 views
Skip to first unread message

stepcut

unread,
Feb 19, 2010, 10:31:59 AM2/19/10
to Haskell Server Pages
Hello,

This test program does not compile under the latest trhsx:

{-# OPTIONS_GHC -fglasgow-exts -F -pgmFtrhsx #-}
import HSP

main = return ()

foo :: (XMLGenerator m) => GenXML m
foo = <head [] />


It gets the error:

Prelude> :load "/tmp/Test.hs"
[1 of 1] Compiling Main ( /tmp/Test.hs, interpreted )

/tmp/Test.hs:7:50:
Couldn't match expected type `a -> b'
against inferred type `GenAttributeList m'
In the first argument of `map', namely `(asAttr [])'
In the second argument of `(++)', namely `map (asAttr [])'
In the second argument of `genEElement', namely
`([] ++ map (asAttr []))'
Failed, modules loaded: none.

Looking at the output of trhsx we see:
$ trhsx Test.hs
{-# LINE 1 "Test.hs" #-}
{-# OPTIONS_GHC -fglasgow-exts -F -pgmFtrhsx #-}
module Main (main) where
{-# LINE 2 "Test.hs" #-}
import HSP
{-# LINE 4 "Test.hs" #-}
main = return ()

{-# LINE 6 "Test.hs" #-}
foo :: (XMLGenerator m) => GenXML m
{-# LINE 7 "Test.hs" #-}
foo = (genEElement (Nothing, "head") ([] ++ map (asAttr [])))

The issue is in the last line where we have, map (asAttr []), instead
of (map asAttr []).

Not sure if this is due to a bug in hsx or haskell-src-exts?

thanks!
- jeremy

stepcut

unread,
Feb 19, 2010, 11:06:35 AM2/19/10
to Haskell Server Pages
I am pretty sure this is the issue. In metaGenEElement is the
construct:

(metaMap $ metaAsAttr x)

Breaking that into pieces we have:

-- | Create an attribute by applying the overloaded @asAttr@
metaAsAttr :: Exp -> Exp
metaAsAttr e = metaFunction "asAttr" [e]

metaMap :: Exp -> Exp
metaMap e = metaFunction "map" [e]

I think it is pretty easy to see that (metaMap $ metaAsAttr x) is
going to be translated to (map $ asAttr x) aka (map (asAttr x)).

We can check that explicitly as well:

*HSX.Transform Language.Haskell.Exts.Pretty> metaMap (metaAsAttr (Lit
(Char 'c')))
App (Var (UnQual (Ident "map"))) (App (Var (UnQual (Ident "asAttr")))
(Lit (Char 'c')))
*HSX.Transform Language.Haskell.Exts.Pretty> prettyPrint $ metaMap
(metaAsAttr (Lit (Char 'c')))
"map (asAttr 'c')"
*HSX.Transform Language.Haskell.Exts.Pretty>

What we want is something more like:

*HSX.Transform Language.Haskell.Exts.Pretty> prettyPrint $
metaFunction "map" [(metaFunction "asAttr" []), Lit (Char 'c')]
"map asAttr 'c'"

Or if we prefer:
*HSX.Transform Language.Haskell.Exts.Pretty> prettyPrint $ app
(metaMap (metaFunction "asAttr" [])) (Lit (Char 'c'))
"map asAttr 'c'"

Or even:
*HSX.Transform Language.Haskell.Exts.Pretty> prettyPrint $ app (app
(metaFunction "map" []) (metaFunction "asAttr" [])) (Lit (Char 'c'))
"map asAttr 'c'"

I would submit a patch, but I am not quite sure how you want to fix
this. The metaFoo functions are in some sense broken, because they
don't support partial application. You could change them all to things
like:

metaMap, metaAsAttr :: Exp
metaMap = metaFunction "map" []
metaAsAttr = metaFunction "asAttr" []

But then you have to use app to apply them:

*HSX.Transform Language.Haskell.Exts.Pretty> prettyPrint $ metaMap
`app` metaAsAttr `app` (Lit (Char 'c'))
"map asAttr 'c'"

On the other hand.. there is a reason why function application is
usually an explicit constructor in ADTs for functional languages :)

- jeremy

Reply all
Reply to author
Forward
0 new messages