{-# OPTIONS -XGADTs #-} data Reader s a where R :: (s -> a) -> Reader s a instance Monad (Reader s) where return x = R (\ _ -> x) (R f) >>= g = R (\s -> case g (f s) of (R f') -> f' s) readst :: Reader s s readst = R (\s -> s) modify :: (s' -> s) -> Reader s a -> Reader s' a modify m (R f) = R (\s' -> f (m s')) run :: Reader s a -> s -> a run (R f) s = f s data Exp where Var :: String -> Exp Const :: Integer -> Exp Plus :: Exp -> Exp -> Exp Let :: String -> Exp -> Exp -> Exp type Env = String -> Integer bind :: String -> Integer -> Env -> Env bind x i old findthis = if x == findthis then i else (old x) eval :: Exp -> Reader Env Integer eval (Var x) = do env <- readst return (env x) eval (Const x) = return x eval (Plus e1 e2) = do i1 <- eval e1 i2 <- eval e2 return (i1 + i2) eval (Let x e1 e2) = do i1 <- eval e1 modify (bind x i1) (eval e2) e1 :: Exp e1 = Let "y" (Plus (Const 1) (Const 2)) (Plus (Let "y" (Const 100) (Var "y")) (Var "y")) initenv :: Env initenv s = undefined