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