-- | Symbolic Expressons -- More exercises with recursive data types -- Functional Programming course 2018. -- Thomas Hallgren {- This started as a skeleton, the definitions were filled in during the lecture. -} module SymbolicExpressions where import Data.List(union) -- | A Haskell data type for arithmetic expressions with variables data Expr = Num Integer | Var Name | Add Expr Expr | Mul Expr Expr deriving (Eq) type Name = String ex1 = Num 2 ex2 = Add (Num 2) (Num 2) ex3 = Mul (Add (Num 1) (Num 2)) (Num 3) ex4 = Add (Num 1) (Mul (Num 2) (Num 3)) ex5 = Add (Mul (Num 2) x) (Mul (Num 3) y) ex6 = Add (Mul (Num 2) (Mul x x)) (Mul (Num 3) y) x = Var "x" y = Var "y" -------------------------------------------------------------------------------- -- * Showing expressions instance Show Expr where show = showExpr showExpr :: Expr -> String showExpr (Add e1 e2) = showExpr e1 ++ "+" ++ showExpr e2 showExpr e = showFactor e showFactor :: Expr -> String showFactor (Mul e1 e2) = showFactor e1 ++ "*" ++ showFactor e2 showFactor (Num n) = show n showFactor (Var s) = s showFactor e = "("++showExpr e++")" -------------------------------------------------------------------------------- -- | Gathering variables vars :: Expr -> [Name] vars (Num n) = [] vars (Var x) = [x] vars (Add a b) = vars a `union` vars b vars (Mul a b) = vars a `union` vars b -- | Substituting expressions for variables substitute :: [(Name,Expr)] -> Expr -> Expr substitute env (Num n) = Num n substitute env (Var x) = case lookup x env of Nothing -> error ("Variable not defined: "++x) Just e -> e substitute env (Add a b) = Add (substitute env a) (substitute env b) substitute env (Mul a b) = Mul (substitute env a) (substitute env b) -------------------------------------------------------------------------------- -- | Evaluating Symbolic Expressions eval :: [(Name,Integer)] -> Expr -> Integer eval env (Num n) = n eval env (Var x) = case lookup x env of Nothing -> error ("Varible not defined: "++x) Just n -> n eval env (Add a b) = eval env a + eval env b eval env (Mul a b) = eval env a * eval env b -------------------------------------------------------------------------------- -- * Symbolic Differentiation -- | Symbolic Differentiation function diff :: Expr -> Name -> Expr diff (Num n) x = Num 0 diff (Var y) x | y==x = Num 1 | otherwise = Num 0 diff (Add a b) x = add (diff a x) (diff b x) diff (Mul a b) x = add (mul (diff a x) b) (mul a (diff b x)) -- * Simplifying expressions by using "smart" constructors -- 0+e == e, e+0 == e, 1*e == e, e*1 == e, 0*e == 0, e*0 == 0 add (Num 0) e = e add e (Num 0) = e add e1 e2 = Add e1 e2 mul (Num 1) e = e mul e (Num 1) = e mul (Num 0) e = Num 0 mul e (Num 0) = Num 0 mul e1 e2 = Mul e1 e2