Hi,

thanks for the last help and hints. I have encountered an other problem,
and again I don't quite understand the reason why I get the results I
get. ghci seems to infer different types for the same expression.

Consider that I have disabled the monomorphism restriction 
in module AGC.lhs (which is attached).

and I have a toplevel definition of:

> mylength = synAttr listLength

loding the module in ghci (6.4) gives (beside some correct warnings):

$ Ok, modules loaded: Main.
$ *Main> :type synAttr
$ synAttr :: (Data b) => ((?stack::[Dyn]) => b -> a) -> Attr a

$ *Main> :type listLength
$ listLength :: (?stack::[Dyn]) => List -> Float

$ *Main> :type (synAttr listLength)
$ (synAttr listLength) :: Attr Float

$ *Main> :type mylength
$ mylength :: (?stack::[Dyn]) => Dyn -> Dyn -> [Dyn] -> Maybe Float

$ *Main> let mylength = synAttr listLength
$ *Main> :type mylength
$ mylength :: Dyn -> Dyn -> [Dyn] -> Maybe Float

where

> type Attr a = Dyn -> Dyn -> [Dyn]-> Maybe a

the problem I have is that inferred types for the toplevel declaration
mylength differ from the verbatim equal definition in the Let
experssion.

for the toplevel it infers:

  mylength :: (?stack::[Dyn]) => Dyn -> Dyn -> [Dyn] -> Maybe Float

for the let-Binding
 
  mylength :: Dyn -> Dyn -> [Dyn] -> Maybe Float

and this is what I expected.

Has anyone an Idea, why this happens?

best regards,

  Eike Scholz

PS: Beware of the comments in the attached file. This file is under
heavy development. I am dyslexic and don't correct the comments 
while continuously rewriting code and comments. I hope that the comments
are useful anyway. 
The (+>) (~>) (#>) operators are broken at the moment and don't work the
way intended.






>{-# OPTIONS_GHC -fglasgow-exts #-}
>{-# OPTIONS_GHC -fno-monomorphism-restriction #-}

> import Data.Typeable 
> import qualified Data.Dynamic as D
> import Data.Generics
> import Data.Maybe
> import Debug.Trace

> strace s = trace (show s) s

------------------------------------------------------------------------------
-- Description:
-- Attribute Grammar Combinators 

trying to model an attribute grammer by an combinator dsl
by going through the example from
 http://www.haskell.org/tmrwiki/WhyAttributeGrammarsMatter
 by Wouter Swierstra for The Monad.Reader Issue Four 01-07-05

lets start with rewriting the test defintions:

DATA Root
  | Root  list : List

DATA List
  | Nil
  | Cons  hd : Float tl : List


> data Root = Root List
>   deriving (Typeable,Data,Show)


> data List = Cons Float List  -- head and tail are in prelude
>           | Nil
>   deriving (Typeable,Data,Show)

now lets look how an attribute and a semantic:

ATTR List [ | | length : Float]

SEM List
  | Nil    lhs.length  = 0.0
  | Cons   lhs.length  = 1.0 + @tail.length

the length value is somehow accessed by 
  
  nodeName.AttrName 
 
we'll use (+>) for (.) since (.) is allready assigned
for the same reason well use mylength

Lets simply define a type specific listLength

> type SynSem c v = (?stack :: [Dyn]) => c -> v

> listLength :: (?stack :: [Dyn]) => List -> Float
> listLength Nil         = 0  -- the "parent" gets explained later
> listLength (Cons _ tl) = (1 + (tl+>mylength) ) -- length is prelude

This is quite straight, but uses the not jet defined attribute mylength,
We can define it with:

> mylength = synAttr listLength

we can define the sum Attribute in the same way:

<> listSum :: SynSem List Float
<> listSum Nil         = 0  -- the "parent" gets explained later
<> listSum (Cons v tl) = (v + (tl+>mysum) ) -- length is prelude

<> mysum = synAttr listSum

well syntesised symantics seem to be simple.

so lets look at the inherited sematics:

ATTR List [ avg : Float | | ]

SEM Root
  | Root   list.avg    = @list.sum / @list.length

SEM List
  | Cons   tail.avg    = @lhs.avg

lets assume we have allready defined the synthesised semantics for sum.

lets look at the cons example: it tells us, 
that the average at the tail is the local average.

With the combinators it is translates to:


<> root_list_Avg :: InhSem Root List Float
<> root_list_Avg (Root _) l  = ((l+>mysum) / (l+>mylength))
 
<> cons_tail_Avg :: InhSem List List Float
<> cons_tail_Avg parent@(Cons _ _) l  = parent~>avg

<> avg = (inhAttr root_list_Avg) -- at this point we want to drop the
<>        ?+ (inhAttr cons_tail_Avg) -- monomorphism restriction
 
now a test type

> tl = (Cons 2 (Cons 8 (Cons 20 (Cons 10 Nil)))) 


when we want to acces a Attribute outside the semantic functions
we have initialise the parent stack

<> l = tl?>mylength

<> s = tl?>mysum

<> av = (Root tl)?>avg


--------------------------------------------------------------------------
-- Implementation

> type InhSem p c v = (?stack :: [Dyn]) => p -> c -> v

> data None = None -- these are special placeohlders
>   deriving (Typeable,Data,Show,Read,Eq)
> data Any  = Any
>   deriving (Typeable,Data,Show,Read,Eq)


the Attr agruments, are the parent, this node, and a stack (list) containing
all parents.

> type Attr a = Dyn -> Dyn -> [Dyn]-> Maybe a

> attr :: forall p b a . (Typeable p,Typeable b) => ((?stack::[Dyn])=>p->b->a) -> Attr a
> attr f p' b' st 
>  = let ?stack = strace ((packDyn b'):st)
>     in if ( typeOf (fstType f) == (typeOf Any))
>         then 
>           if typeOf (sndType f) == (typeOf Any)
>             then Just (f dynAny dynAny') -- matches anything
>             else if storedType b' == (typeOf (sndType f)) -- we are plain syn
>                    then Just (f dynAny (fromDyn b')) 
>                    else Nothing
>         else if storedType p' == (typeOf (fstType f))  -- we are inh.
>                then if typeOf (sndType f) == (typeOf Any)
>                       then Just (f (fromDyn p') dynAny')  -- we are plain inh.
>                       else if storedType b' == (typeOf (sndType f))
>                              then Just (f (fromDyn p') (fromDyn b'))-- syn&inh
>                              else Nothing
>                else Nothing
>   where
>    dynAny   = fromDyn (toDyn Any)
>    dynAny'  = fromDyn (toDyn Any) -- fighting monomorphism restriction


any should match Any type but the "None" type, since this is a 
placeholder for an undefined type

recreating th synAttr

> synAttr :: (Data b) => ((?stack::[Dyn])=>b->a) -> Attr a
> synAttr f = attr (conv f)
>  where
>   conv :: ((?stack::[Dyn]) => b -> a) -> ((?stack::[Dyn]) => Any -> b -> a)
>   conv f = \Any c -> f c


<> inhAttr = attr 


> parent :: (?stack::[Dyn]) => Dyn
> parent = if length ?stack > 1
>           then (?stack)!!1
>           else (toDyn None)

> this :: (?stack::[Dyn]) => Dyn
> this = if length ?stack > 0
>         then (?stack)!!0
>         else (toDyn None)


> packDyn d = if typeOf d == typeOf (udef::Dyn)
>              then D.fromDyn (D.toDyn d) udef
>              else toDyn d
> 

> (+>) :: (?stack :: [Dyn] , Data t) => t -> Attr a -> a
> (+>) t f 
>  = let st = ?stack -- this is quite irritating
>     in case (f parent this st) of       -- its not an infinite list, its an update
>         (Just a) -> a
>         Nothing  -> error ("local lookup (+>) failed:\n"++noSemFoundErr)


-- acces a parents value

> (~>) :: (?stack :: [Dyn] , Data t) => t -> Attr a -> a
> (~>) t f = let st = tail ?stack 
>             in case f p (toDyn t) st of
>                 (Just a) -> a
>                 Nothing  -> error ("parent lookup (~>) failed:\n"
>                                     ++noSemFoundErr )
>  where
>   p  = head ?stack
>   ns = tail ?stack

-- acces from outside

> (?>) :: Data t => t -> Attr a -> a
> (?>) = let ?stack = [] in (+>)


 
we need a way to join semantics
this operator will try the first sem, then the second

> (?+) :: Attr a -> Attr a -> Attr a
> (?+) s1 s2 p t st 
>    = case s1 p t st of
>        Nothing  -> case s2 p t st of
>                      Nothing  -> error ("no semantics found for type \""
>                                          ++(show (storedType t))
>                                          ++"\" with parent of type \""
>                                          ++(show (storedType p))++"\"" )
>                      ma       -> ma
>        ma       -> ma


> noSemFoundErr :: (?stack::[Dyn]) => a
> noSemFoundErr 
>  = error ("no semantics found for type \""
>            ++(show (storedType this))
>            ++"\" with parent of type \""
>            ++(show (storedType parent))++"\"" )


------------------------------------------------------------------------------
-- auxillary functions and definitions:

> udef = undefined  

> fstType :: (a->b) -> a
> fstType f = udef

> sndType :: (a->b->c) -> b
> sndType f = udef

> data Dyn = Dyn TypeRep (D.Dynamic) [Dyn]
>  deriving (Typeable)

> toDyn :: Data a => a -> Dyn
> toDyn x = Dyn (typeOf x) (D.toDyn x) (mkDyns (gmapQ mk x))
>  where
>   mk :: Data a' => a' -> (TypeRep,D.Dynamic,[Dyn]) 
>   mk    x' = (typeOf x',D.toDyn x',mkDyns (gmapQ mk  x') )
>   mkDyn (t,v,r) = Dyn t v r
>   mkDyns xs = map mkDyn xs
>   ns = (gmapQ mk x)

> instance Show Dyn where
>  show (Dyn _ d _ ) = show d


> tryFromDyn (Dyn _ d _)  = D.fromDynamic d
> fromDyn (Dyn _ d _)     = (D.fromDyn d) (error "invalid cast from Dyn")
> storedType (Dyn t _ _)  = t
> dynContents (Dyn _ _ c) = c


> instance Data Dyn where

this is a hack, we actually don't need the implementation.
however packDyn needs this instance



------------------------------------------------------------------------------
-- test garbedge 

<> (???) :: ( (?foo::Int) => b -> a) -> b -> a
<> (???) f x
<>  = let ?foo = 1337
<>     in f x

<> fun :: (?foo::Int,Show x) => x -> String
<> fun x =  "x = "++(show x)++"; ?foo = "++(show ?foo) 

<> test = (fun???)

<> undef = error ?errstr

<> (<?>) x s = let ?errstr = ?errstr++"\n"++s in x


_______________________________________________
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell

Reply via email to