multirec-0.1: examples/ASTExamples.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module ASTExamples where
import Data.Maybe (fromJust)
import Control.Arrow ((>>>))
import Control.Monad ((>=>))
import AST
import Generics.MultiRec.Base
import Generics.MultiRec.Compos
import Generics.MultiRec.Fold
import Generics.MultiRec.Eq
-- | Example expression
example = Let ("x" := Mul (Const 6) (Const 9))
(Add (EVar "x") (EVar "y"))
-- | Renaming variables using 'compos'
renameVar :: Expr -> Expr
renameVar = renameVar' Expr
where
renameVar' :: Ix AST a => AST a -> a -> a
renameVar' Var x = x ++ "_"
renameVar' _ x = compos renameVar' x
-- | Test for 'renameVar'
testRename :: Expr
testRename = renameVar example
-- | Result of evaluating an expression
data family Value aT :: *
data instance Value Expr = EV (Env -> Int)
data instance Value Decl = DV (Env -> Env)
data instance Value Var = VV Var
type Env = [(Var, Int)]
-- | Algebra for evaluating an expression
evalAlgebra :: Algebra AST Value
evalAlgebra _ =
tag (\ (K x) -> EV (const x))
& tag (\ (I (EV x) :*: I (EV y)) -> EV (\ env -> x env + y env))
& tag (\ (I (EV x) :*: I (EV y)) -> EV (\ env -> x env * y env))
& tag (\ (I (VV x)) -> EV (fromJust . lookup x))
& tag (\ (I (DV e) :*: I (EV x)) -> EV (\ env -> x (e env)))
& tag (\ (I (VV x) :*: I (EV v)) -> DV (\ env -> (x, v env) : env ))
& tag (\ (I (DV f) :*: I (DV g)) -> DV (g . f))
& tag (\ (K x) -> VV x)
-- | Evaluator
eval :: Expr -> Env -> Int
eval x = let (EV f) = fold evalAlgebra x in f
-- | Test for 'eval'
testEval :: Int
testEval = eval example [("y", -12)]
-- | Equality instance for 'Expr'
instance Eq Expr where
(==) = eq Expr
-- | Test for equality
testEq :: (Bool, Bool)
testEq = (example == example, example == testRename)