-- | Arithmetic Quiz -- An exercise with recursive data types -- Functional Programming course 2017. -- Thomas Hallgren {- This stared as a skeleton, the definitions were filled in during the lecture. -} -------------------------------------------------------------------------------- import Control.Monad(forever) import Test.QuickCheck main :: IO () main = do putStrLn "Welcome to the arithmetic quiz!" forever quiz quiz :: IO () quiz = do e <- generate rExpr putStrLn ("What is "++showExpr e++"?") answer <- readLn if answer == eval e then putStrLn "Yes, that is correct!" else putStrLn ("Sorry, the correct answer is: "++show (eval e)) -- | A representation of simple arithmetic expressions data Expr = Num Integer | Add Expr Expr | Mul Expr Expr 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 -- | Computing the value of an expression eval :: Expr -> Integer eval (Num n) = n eval (Add a b) = eval a + eval b eval (Mul a b) = eval a * eval b -- | Showing expressions showExpr :: Expr -> String showExpr (Num n) = show n showExpr (Add a b) = showExpr a ++ "+" ++ showExpr b showExpr (Mul a b) = showFactor a ++ "*" ++ showFactor b showFactor (Add a b) = "("++showExpr (Add a b)++")" showFactor e = showExpr e instance Show Expr where show = showExpr -- * Generating arbitrary expressions -- | Random generator with bad control over expression sizes rExpr_v1 :: Gen Expr rExpr_v1 = oneof [elements [Num n|n<-[1..10]], do op <- elements [Add,Mul] e1 <- rExpr_v1 e2 <- rExpr_v1 return (op e1 e2)] -- | Random generator with exact control of the number of operators rExpr_v2 :: Int -> Gen Expr rExpr_v2 0 = elements [Num n|n<-[1..10]] rExpr_v2 n = do op <- elements [Add,Mul] n' <- elements [0 .. n-1] e1 <- rExpr_v2 n' e2 <- rExpr_v2 (n-1 - n') return (op e1 e2) -- | Random generator with some variation in size rExpr :: Gen Expr rExpr = do n <- elements [1..3] rExpr_v2 n --instance Arbitrary Expr where arbitrary = {- Below are the tests we ran in GHCi: :load ArithmeticQuiz.hs eval ex1 eval ex2 eval ex3 eval ex4 :r ex3 showExpr ex3 showExpr ex4 :r showExpr ex4 showExpr ex3 :i Show :i (*) :i (+) :r showExpr ex3 showExpr ex4 ex12 ex2 showExpr ex2 showExpr ex1 :r ex4 :t oneof :t elements :t Add :r sample rExpr :r rExpr 0 sample (rExpr 0) sample (rExpr 1) sample (rExpr 2) sample (rExpr 3) sample (rExpr 3) :r sample rExpr sample rExpr :t generate :t readLn :r main :r :t forever :r main :r sample rExpr main -}