Skip to content

Instantly share code, notes, and snippets.

newtype Fix f = Fix { unFix :: f (Fix f) }
-- Analog to Expr = ExprR Expr
type Expr = Fix ExprR
cst = Fix . Cst
var = Fix . Var
add = Fix . Op Add
mul = Fix . Op Mul
> 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") ]]
instance Functor ExprR where
fmap _ (Cst c) = Cst c
fmap _ (Var v) = Var v
fmap f (Op opType xs) = Op opType (map f xs)
cataExpr :: (ExprR a -> a) -> Expr -> a
cataExpr algebra =
algebra
. fmap (cataExpr algebra)
. unFix
cata :: Functor f => (f a -> a) -> Fix f -> a
cata algebra =
algebra
. fmap (cata algebra)
. unFix
prn :: Expr -> String
prn = cata algebra where
algebra (Cst n) = show n
algebra (Var x) = x
algebra (Op Add xs) = "(+ " ++ unwords xs ++ ")"
algebra (Op Mul xs) = "(* " ++ unwords xs ++ ")"
eval :: Env -> Expr -> Int
eval env = cata algebra where
algebra (Cst n) = n
algebra (Var x) = env Map.! x
algebra (Op Add xs) = sum xs
algebra (Op Mul xs) = product xs
dependencies :: Expr -> Set.Set Id
dependencies = cata algebra where
algebra (Cst _) = Set.empty
algebra (Var x) = Set.singleton x
algebra (Op _ xs) = Set.unions xs
optimizeAdd :: ExprR Expr -> Expr
optimizeAdd op@(Op Add _) = optimizeOp op 0 (+)
optimizeAdd e = Fix e
optimizeMul :: ExprR Expr -> Expr
optimizeMul op@(Op Mul xs)
| not (null (dropWhile (/= cst 0) xs)) = cst 0
| otherwise = optimizeOp op 1 (*)
optimizeMul e = Fix e