import Data.Maybe import Control.Monad import Data.Map.Lazy import Prelude hiding (lookup) newtype Reader e a = Reader { runReader :: (e -> a) } instance Functor (Reader e) where fmap = liftM instance Applicative (Reader e) where pure a = Reader $ \e -> a (<*>) = ap instance Monad (Reader e) where return a = Reader $ \e -> a (Reader r) >>= f = Reader $ \e -> runReader (f (r e)) e ask :: Reader e e ask = Reader id local :: (e -> e) -> Reader e a -> Reader e a local f c = Reader $ \e -> runReader c (f e) type ID = String data Exp = Num Int | Add Exp Exp | Var ID | Let ID Exp Exp eval :: Exp -> Reader (Map ID Int) Int eval (Num n) = return n eval (Add e e') = do a <- eval e b <- eval e' return (a + b) eval (Var v) = do s <- ask return (fromJust $ lookup v s) eval (Let v e b) = do a <- eval e local (insert v a) (eval b) evalAmb :: Exp -> Map ID Int -> Int evalAmb = runReader . eval amb :: Map ID Int amb = insert "x" 5 empty ejemplo1 = Add (Num 8) (Var "x") ejemplo2 = Add (Num 2) (Let "x" (Num 3) ejemplo1)