Last active
June 4, 2023 20:14
-
-
Save Lev135/b6fa3c47387801198daa0590ccd08d65 to your computer and use it in GitHub Desktop.
Eval by need (with named varriables)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Data.Either.Extra (maybeToEither) | |
data Expr | |
= Var String | |
| Lam String Expr | |
| App Expr Expr | |
| Lit Int | |
| Prim PrimOp Expr Expr | |
deriving (Show) | |
data Value | |
= VInt Int | |
| VClosure String Expr Env | |
deriving (Show) | |
data PrimOp = Add | Mul deriving (Show) | |
type Env = [(String, Value)] | |
data EvalError | |
= UndefinedVar String | |
| Unaplicable Value | |
| IncorrectArgs PrimOp Value Value | |
deriving (Show) | |
eval :: Env -> Expr -> Either EvalError Value | |
eval env term = case term of | |
Var n -> maybeToEither (UndefinedVar n) $ lookup n env | |
Lam n a -> pure $ VClosure n a env | |
App a b -> do | |
aRes <- eval env a | |
case aRes of | |
VClosure n c env' -> do | |
bRes <- eval env b | |
eval ((n, bRes) : env') c | |
x -> | |
Left $ Unaplicable x | |
Lit n -> | |
pure $ VInt n | |
Prim p a b -> do | |
resA <- eval env a | |
resB <- eval env b | |
evalPrim p resA resB | |
evalPrim :: PrimOp -> Value -> Value -> Either EvalError Value | |
evalPrim Add (VInt a) (VInt b) = pure $ VInt (a + b) | |
evalPrim Mul (VInt a) (VInt b) = pure $ VInt (a + b) | |
evalPrim op x1 x2 = Left $ IncorrectArgs op x1 x2 | |
emptyEnv :: Env | |
emptyEnv = [] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment