|
| 1 | +module Transformers where |
| 2 | + |
| 3 | + import Control.Monad.Identity |
| 4 | + import Control.Monad.Except |
| 5 | + import Control.Monad.Reader |
| 6 | + import Control.Monad.State |
| 7 | + import Control.Monad.Writer |
| 8 | + import Data.Maybe |
| 9 | + import qualified Data.Map as Map |
| 10 | + |
| 11 | + type Name = String |
| 12 | + data Exp = Lit Integer |
| 13 | + | Var Name |
| 14 | + | Plus Exp Exp |
| 15 | + | Abs Name Exp |
| 16 | + | App Exp Exp |
| 17 | + deriving (Show) |
| 18 | + |
| 19 | + data Value = IntVal Integer |
| 20 | + | FunVal Env Name Exp |
| 21 | + deriving (Show) |
| 22 | + |
| 23 | + type Env = Map.Map Name Value |
| 24 | + |
| 25 | + eval0 :: Env -> Exp -> Value |
| 26 | + eval0 env (Lit i) = IntVal i |
| 27 | + eval0 env (Var n) = fromJust (Map.lookup n env) |
| 28 | + eval0 env (Plus e1 e2) = let IntVal i1 = eval0 env e1 |
| 29 | + IntVal i2 = eval0 env e2 |
| 30 | + in IntVal (i1 + i2) |
| 31 | + eval0 env (Abs n e) = FunVal env n e |
| 32 | + eval0 env (App e1 e2) = let val1 = eval0 env e1 |
| 33 | + val2 = eval0 env e2 |
| 34 | + in case val1 of |
| 35 | + FunVal env' n body -> eval0 (Map.insert n val2 env') body |
| 36 | + |
| 37 | + type Eval1 a = Identity a |
| 38 | + |
| 39 | + runEval1 :: Eval1 a -> a |
| 40 | + runEval1 ev = runIdentity ev |
| 41 | + |
| 42 | + eval1 :: Env -> Exp -> Eval1 Value |
| 43 | + eval1 env (Lit i) = return $ IntVal i |
| 44 | + eval1 env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env |
| 45 | + eval1 env (Plus e1 e2) = do val1 <- eval1 env e1 |
| 46 | + val2 <- eval1 env e2 |
| 47 | + case (val1, val2) of |
| 48 | + (IntVal i1, IntVal i2) -> |
| 49 | + return $ IntVal (i1 + i2) |
| 50 | + eval1 env (Abs n e) = return $ FunVal env n e |
| 51 | + eval1 env (App e1 e2) = do val1 <- eval1 env e1 |
| 52 | + val2 <- eval1 env e2 |
| 53 | + case val1 of |
| 54 | + FunVal env' n body -> |
| 55 | + eval1 (Map.insert n val2 env') body |
| 56 | + |
| 57 | + type Eval2 a = ExceptT String Identity a |
| 58 | + |
| 59 | + runEval2 :: Eval2 a -> Either String a |
| 60 | + runEval2 ev = runIdentity (runExceptT ev) |
| 61 | + |
| 62 | + eval2a :: Env -> Exp -> Eval2 Value |
| 63 | + eval2a env (Lit i) = return $ IntVal i |
| 64 | + eval2a env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env |
| 65 | + eval2a env (Plus e1 e2) = do val1 <- eval2a env e1 |
| 66 | + val2 <- eval2a env e2 |
| 67 | + case (val1, val2) of |
| 68 | + (IntVal i1, IntVal i2) -> |
| 69 | + return $ IntVal (i1 + i2) |
| 70 | + eval2a env (Abs n e) = return $ FunVal env n e |
| 71 | + eval2a env (App e1 e2) = do val1 <- eval2a env e1 |
| 72 | + val2 <- eval2a env e2 |
| 73 | + case val1 of |
| 74 | + FunVal env' n body -> |
| 75 | + eval2a (Map.insert n val2 env') body |
| 76 | + |
| 77 | + eval2b :: Env -> Exp -> Eval2 Value |
| 78 | + eval2b env (Lit i) = return $ IntVal i |
| 79 | + eval2b env (Var n) = maybe (fail ("undefined variable: " ++ n)) return $ Map.lookup n env |
| 80 | + eval2b env (Plus e1 e2) = do val1 <- eval2b env e1 |
| 81 | + val2 <- eval2b env e2 |
| 82 | + case (val1, val2) of |
| 83 | + (IntVal i1, IntVal i2) -> |
| 84 | + return $ IntVal (i1 + i2) |
| 85 | + _ -> throwError "type error: IntVal expected" |
| 86 | + eval2b env (Abs n e) = return $ FunVal env n e |
| 87 | + eval2b env (App e1 e2) = do val1 <- eval2b env e1 |
| 88 | + val2 <- eval2b env e2 |
| 89 | + case val1 of |
| 90 | + FunVal env' n body -> |
| 91 | + eval2b (Map.insert n val2 env') body |
| 92 | + _ -> throwError "type error: FunVal expected" |
0 commit comments