Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module Expr where
- import Parsing
- import Data.Char(isDigit, isSpace)
- import Data.Maybe
- import Test.QuickCheck
- import Control.Monad(forever)
- --Expressions for testing
- ex1 = Num 2 -- 2
- ex2 = Add (Num 1) (Num 2) -- 1 + 2
- ex3 = Mul (Add (Num 1) (Num 2)) (Num 3) -- (1+2)*3
- ex4 = Add (Num 1) (Mul (Num 2) (Num 3)) -- 1+2*3
- ex5 = Sin (Add (Num 1) (Num 5)) -- sin (1+5)
- ex6 = Sin (Mul (Num 7) (Var))
- ex8 = Mul (Mul (Num 6) (Num 1)) (Var)
- ex7 = Add (Mul (Num 6) (Num 1)) (Var)
- ex9 = Cos (Mul (Num 7) (Var))
- -- * A
- --Representation of mathematic operators and fuctions
- data Expr = Num Double
- | Var
- | Add Expr Expr
- | Mul Expr Expr
- | Sin Expr
- | Cos Expr
- deriving Show
- -- * B
- -- Converts any expression to string
- showExpr :: Expr -> String
- showExpr (Num n) = show n
- showExpr (Var) = "x"
- showExpr (Add a b) = showExpr a ++ "+" ++ showExpr b
- showExpr (Mul a b) = showFactor a ++ "*" ++ showFactor b
- showExpr (Sin a) = "sin" ++ showTrig a
- showExpr (Cos a) = "cos" ++ showTrig a
- showFactor :: Expr -> String
- showFactor e@(Add _ _) = "("++ showExpr e ++")"
- showFactor e = showExpr e
- showTrig :: Expr -> String
- showTrig e@(Add a b) = "(" ++ showExpr e ++")"
- showTrig e@(Mul a b) = "(" ++ showExpr e ++")"
- showTrig e = showExpr e
- -- * C
- -- Calculates the value of teh expression given
- -- an expression and a value for x
- eval :: Expr -> Double -> Double
- eval (Num n) x = n
- eval Var x = x
- eval (Add a b) x = eval a x + eval b x
- eval (Mul a b) x = eval a x * eval b x
- eval (Sin a) x = sin (eval a x)
- eval (Cos a) x = cos (eval a x)
- -- * D
- -- top level parser
- -- remove spaces and expect no junk!
- -- Interpret the string as an expression
- readExpr :: String -> Maybe Expr
- readExpr s = let s' = filter (not.isSpace) s
- in case parse expr s' of
- Just (e,"") -> Just e
- _ -> Nothing
- expr, term, factor, sinn, coss :: Parser Expr
- expr = leftAssoc Add term (char '+')
- term = leftAssoc Mul factor (char '*')
- sinn = Sin <$> ((string "sin") *> factor)
- coss = Cos <$> ((string "cos") *> factor)
- factor = (Num <$> readsP) <|> (char '(' *> expr <* char ')') <|>
- sinn <|> coss <|> (char 'x' *> return Var)
- leftAssoc :: (t->t->t) -> Parser t -> Parser sep -> Parser t
- leftAssoc op item sep = do is <- chain item sep
- return (foldl1 op is)
- string :: String -> Parser String
- string s = sequence $ fmap (char) s
- -- * E
- -- Checks if showing and then reading an expression
- -- gives the same result as the expression it started with
- prop_ShowReadExpr :: Expr -> Bool
- prop_ShowReadExpr e = let s = showExpr e
- Just e' = readExpr s
- in showExpr e' == s
- -- Generates expressions
- arbExpr :: Int -> Gen Expr
- arbExpr s = frequency [(1,rNum),(s,rOp),(s,sOp), (1,return Var)]
- where
- s' = s `div` 2
- rNum = do
- n <- arbitrary
- return $ Num n
- rOp = do
- op <- elements [Add,Mul]
- e1 <- arbExpr s'
- e2 <- arbExpr s'
- return $ op e1 e2
- sOp = do
- op1 <- elements [Sin,Cos]
- x1 <- arbExpr s'
- return $ op1 x1
- instance Arbitrary Expr where
- arbitrary = sized arbExpr
- -- * F
- --
- simplify :: Expr -> Expr
- simplify e = simpLoop e 100
- where simpLoop e 0 = simplify' e
- simpLoop e i = simpLoop (simplify' e) (i-1)
- simplify' :: Expr -> Expr
- simplify' (Add (Num a) (Num b)) = (Num (a+b))
- simplify' (Mul (Num 0) _) = Num 0
- simplify' (Mul _ (Num 0)) = Num 0
- simplify' (Mul (Num a) (Num b)) = (Num (a*b))
- simplify' (Add ex1 ex2) = (Add (simplify' ex1) (simplify' ex2))
- simplify' (Mul ex1 ex2) = (Mul (simplify' ex1) (simplify' ex2))
- simplify' (Sin ex) = (Sin (simplify' ex))
- simplify' (Cos ex) = (Cos (simplify' ex))
- simplify' ex = ex
- prop_simplify :: Expr -> Double -> Bool
- prop_simplify e x = (eval e x) == (eval (simplify e) x)
- -- * G
- --
- differentiate :: Expr -> Expr
- differentiate e = simplify $ differentiate' $ simplify e
- differentiate' :: Expr -> Expr
- differentiate' (Num _) = Num 0
- differentiate' Var = Num 1
- differentiate' (Mul ex1 Var) = ex1
- differentiate' (Mul Var ex2) = ex2
- differentiate' (Mul ex1 ex2) = Add (Mul ex1 (differentiate' ex2)) (Mul (differentiate' ex1) ex2)
- differentiate' (Add ex1 ex2) = Add (differentiate' ex1) (differentiate' ex2)
- differentiate' (Sin ex) = Mul (Cos ex) (differentiate' ex)
- differentiate' (Cos ex) = Mul (Mul (Num (-1)) (Sin ex)) (differentiate' ex)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement