app-lens-0.1.0.0: Examples/Evaluator.hs
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
module Examples.Evaluator where
import Control.LensFunction
import Data.Traversable (Traversable)
import Data.Foldable (Foldable)
import Control.Lens
data Exp = ENum Integer
| EInc Exp
| EFun String Exp
| EApp Exp Exp
| EVar String
deriving (Eq, Show)
data Val a = VNum a
| VFun String Exp (Env a)
deriving (Eq, Functor, Foldable, Traversable, Show)
newtype Env a = Env [(String, Val a)]
deriving (Eq, Functor, Foldable, Traversable, Show)
lkup x (Env env) = case lookup x env of
Just v -> v
Nothing -> error $ "Undefined variable: " ++ x
xtnd (x,e) (Env env) = Env $ (x,e):env
incL = lens' $ \s -> (s + 1, \v -> v - 1)
eval :: Exp -> Env (L s Integer) -> Val (L s Integer)
eval (ENum n) env = VNum (new n)
eval (EInc e) env =
let VNum n = eval e env
in VNum (lift incL n)
eval (EFun x e) env =
VFun x e env
eval (EApp e1 e2) env =
let VFun x e env' = eval e1 env
v2 = eval e2 env
in eval e (xtnd (x,v2) env')
eval (EVar x) env = lkup x env
infixl 9 @@ -- @@ is left associative
(@@) = EApp
expr = twice @@ twice @@ twice @@ twice @@ inc @@ x
where
twice = EFun "f" $ EFun "x" $
EVar "f"@@ (EVar "f" @@ EVar "x")
inc = EFun "x" (EInc (EVar "x"))
x = EVar "x"
evalL e = unliftT (\env -> sequenceL $ eval e env)
env0 = Env [("x", VNum 3)]
envn n = Env $ [("x", VNum 3)] ++ [ ("y" ++ show i, VNum i) | i <- [1..n] ]
{-
*Examples.Evaluator> env0 ^. evalL expr
VNum 65539
*Examples.Evaluator> env0 & evalL expr .~ (VNum 0)
Env [("x",VNum (-65536))]
-}