module Expr where -- | Variable names. type Var = String -- | Abstract syntax. data Expr = Lit Int | Add Expr Expr | Let Var Expr Expr | Ref Var deriving (Eq,Show) -- | Environment. type Env = Var -> Maybe Int -- | Empty environment. empty :: Env empty = \_ -> Nothing -- | Extend the environment. extend :: Var -> Int -> Env -> Env extend x i m = \y -> if x == y then Just i else m y -- | Denotational semantics. eval :: Expr -> Env -> Maybe Int eval (Lit i) m = Just i eval (Add l r) m = case (eval l m, eval r m) of (Just i, Just j) -> Just (i+j) _ -> Nothing eval (Let x b e) m = case eval b m of Just i -> eval e (extend x i m) _ -> Nothing eval (Ref x) m = m x -- Examples. ex1 = Let "x" (Lit 3) $ Let "y" (Lit 4) $ Let "z" (Add (Ref "x") (Ref "y")) $ Add (Ref "z") (Ref "z") ex2 = Let "x" (Lit 3) (Add (Ref "x") (Ref "y")) ex3 = Let "x" (Lit 3) (Add (Let "x" (Lit 4) (Ref "x")) (Ref "x"))