Skip to content

Instantly share code, notes, and snippets.

@Lev135
Last active June 4, 2023 20:14
Show Gist options
  • Save Lev135/b6fa3c47387801198daa0590ccd08d65 to your computer and use it in GitHub Desktop.
Save Lev135/b6fa3c47387801198daa0590ccd08d65 to your computer and use it in GitHub Desktop.
Eval by need (with named varriables)
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