-- | Arithmetic Quiz -- An exercise with recursive data types -- Functional Programming course 2016. -- Thomas Hallgren import Control.Monad(forever) import Test.QuickCheck main = do putStrLn "Welcome to the Arithmetic Quiz!" forever quiz quiz = do e <- generate rExpr' putStr ("\n"++showExpr e++" = ") answer <- getLine let correct = show (eval e) putStrLn (if answer == correct then "Correct!" else "Wrong! The correct answer is: "++correct) -- | A representation of simple arithmetic expressions data Expr = Num Integer | Add Expr Expr | Mul Expr Expr deriving (Eq{-,Show-}) ex1 = Num 2 ex2 = Add (Num 1) (Num 2) ex3 = Mul (Add (Num 1) (Num 2)) (Num 3) ex4 = Add (Num 1) (Mul (Num 2) (Num 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 :: Expr -> String showFactor (Add a b) = "("++showExpr (Add a b)++")" showFactor e = showExpr e instance Show Expr where show = showExpr -- * Generating arbitrary expressions rExpr :: Int -> Gen Expr rExpr size = frequency [(1,rNum),(size,rBin)] where rNum = elements [Num n | n<-[0..10]] rBin = do op <- elements [Add,Mul] let size' = size `div` 2 a <- rExpr size' b <- rExpr size' return (op a b) rExpr' = rExpr 3 `suchThat` notNum notNum (Num _) = False notNum _ = True instance Arbitrary Expr where arbitrary = sized rExpr