--
class Add arg1 arg2 res | arg1 arg2 -> res where
plus :: arg1 -> arg2 -> res
instance Add Int Int Int where
plus = primIntAdd
instance Add Float Float Float where
plus = primFloatAdd
instance Add Int Float Float where
plus x y = (int2Float x) + y
----------------------------------
primFloatAdd :: Float -> Float -> Float
primFloatAdd x y = x+y
primIntAdd :: Int -> Int -> Int
primIntAdd x y = x+y
int2Float :: Int -> Float
int2Float x = fromInt x
--------------------------------------------
-- Implicit parameters
data Term
= Int Int
| Plus Term Term
| Let String Term Term
| Var String
eval :: (String -> Int) -> Term -> M Int
eval env t = case t of
Int n -> return n
Var s -> return(env s)
Plus x y -> do { a <- eval env x
; b <- eval env y
; return(a+b)}
Let s x y -> do { a <- eval env x
; eval (newenv a) y }
where newenv a z = if s==z then a else env z
-----------------------------------------------------------
instance Show Term where
show (Int n) = show n
show (Var x) = x
show (Plus x y) = "("++(show x)++"+"++(show y)++")"
show (Let s x y) = "let "++s++" = "++show x++" in "++show y
data M a = M(a,String)
instance Monad M where
return x = M(x,"")
(>>=) (M(a,s1)) f = M(case f a of
M(b,s2) -> (b,s1++s2))
pp :: String -> M ()
pp s = M((),s)
instance Show a => Show(M a) where
show (M(x,y)) = show x ++ "\n "++show y
env "y" = 1
env y = error ("Not known: "++y)
ex1 = Let "x"
(Plus (Int 3) (Var "y"))
(Plus (Var "x") (Plus (Int 5) (Var "y")))
copies 0 s = ""
copies n s = s++(copies (n-1) s)
eval2 :: (?depth :: Int) => (String -> Int) -> Term -> M Int
eval2 env t =
do { pp (copies (?depth * 3) " ")
; pp ("=> "++(show t))
; pp "\n"
; ans <- (case t of
Int n -> return n
Var s -> return(env s)
Plus x y -> do { a <- eval2 env x
; b <- eval2 env y
; return(a+b)}
Let s x y -> do { a <- eval2 env x
; eval2 (newenv a) y }
where newenv a z = if s==z then a else env z)
with ?depth = ?depth + 1
; pp (copies (?depth * 3) " ")
; pp ("<= "++(show ans))
; pp "\n"
; return ans
}
putM :: M a -> IO ()
putM (M(_,s)) = putStrLn s
a1 = putM (eval2 env ex1 with ?depth = 0)
entering :: (?depth :: Int, Show b) => b -> M ()
entering t =
do { pp (copies (?depth * 3) " ")
; pp ("=> "++(show t))
; pp "\n"
}
leaving :: (?depth :: Int, Show b) => b -> M ()
leaving ans =
do { pp (copies (?depth * 3) " ")
; pp ("<= "++(show ans))
; pp "\n"
}
--trace :: (?depth :: Int) => (?depth::Int => Term -> M Int) -> Term -> M Int
trace f t =
do { entering t
; let d = ?depth
; pp "AA"
; pp (show d)
; pp "ZZ"
; ans <- (f t) with ?depth = d + 1
; leaving ans
; return ans
}
--eval3 :: (?depth :: Int) => ([Char] -> Int) -> Term -> M Int
eval3 env t = trace eval3f t
where eval3f (Int n) = return n
eval3f (Var s) = return(env s)
eval3f (Plus x y) =
do { a <- eval3 env x
; b <- eval3 env y
; return(a+b)}
eval3f (Let s x y) =
do { a <- eval3 env x
; eval3 (newenv a) y }
where newenv a z = if s==z then a else env z
a2 = putM ((eval3 env ex1) with ?depth = 0)
--