Skip to content

Instantly share code, notes, and snippets.

type Env = Map.Map String Int
eval :: Env -> Expr -> Int
eval env (Cst n) = n
eval env (Var v) = env Map.! v
eval env (Op Add xs) = sum $ map (eval env) xs
eval env (Op Mul xs) = product $ map (eval env) xs
optimize :: Expr -> Expr
optimize op@(Op Add ys) = optimizeOp Add (map optimize ys) 0 (+)
optimize op@(Op Mul ys)
| not (null (dropWhile (/= cst 0) xs)) = cst 0
| otherwise = optimizeOp Mul xs 1 (*)
where xs = map optimize ys
optimize e = e
optimizeOp :: OpType -> [Expr] -> Int -> (Int -> Int -> Int) -> Expr
optimizeOp opType xs neutral combine =
partial :: Env -> Expr -> Expr
partial env e@(Var v) =
case Map.lookup v env of
Nothing -> e
Just n -> cst n
partial env (Op opType xs) = Op opType (map (partial env) xs)
partial env e = e
dependencies :: Expr -> Set.Set Id
dependencies (Var v) = Set.singleton v
dependencies (Op _ xs) = foldl1' Set.union (map dependencies xs)
dependencies e = Set.empty
eval' :: Env -> Expr -> Int
eval' env e =
case optimize (partial env e) of
Cst n -> n
e -> error $ "Missing vars: " ++ show (dependencies e)
> let e = add [ cst(1)
, cst(2)
, mul [cst(0), var("x"), var("y")]
, mul [cst(1), var("y"), cst(2)]
, add [cst(0), var("x") ]]
> prn e
"(+ 1 2 (* 0 x y) (* 1 y 2) (+ 0 x))"
> prn (optimize e)
> let e = add [ cst(1)
, cst(2)
, mul [cst(0), var("x"), var("y")]
, mul [cst(1), var("y"), cst(2)]
, add [cst(0), var("x") ]]
> let env = Map.fromList [("y", 0)]
> prn (partial env e)
"(+ 1 2 (* 0 x 0) (* 1 0 2) (+ 0 x))"
> prn (partial env e)
"(+ 1 2 (* 0 x 0) (* 1 0 2) (+ 0 x))"
> prn (optimize (partial env e))
"(+ 3 x)"
> let e = add [ cst(1)
, cst(2)
, mul [cst(0), var("x"), var("y")]
, mul [cst(1), var("y"), cst(2)]
, add [cst(0), var("x") ]]
> let env = Map.fromList [("x", 1), ("y", 2)]
> prn e
"(+ 1 2 (* 0 x y) (* 1 y 2) (+ 0 x))"
> let e = add [ cst(1)
, cst(2)
, mul [cst(0), var("x"), var("y")]
, mul [cst(1), var("y"), cst(2)]
, add [cst(0), var("x") ]]
> let env = Map.fromList [("x", 1)]
> eval' env e
*** Exception: Missing vars: fromList ["y"]
type Id = String
data OpType = Add | Mul deriving (Show, Eq, Ord)
data ExprR r
= Cst Int
| Var Id
| Op OpType [r]
deriving (Show, Eq, Ord)