-- | Arithmetic Quiz -- An exercise with recursive data types -- Functional Programming course 2018. -- Thomas Hallgren {- This started as a skeleton, the definitions were filled in during the lecture. -} import Control.Monad(forever) -------------------------------------------------------------------------------- import Test.QuickCheck main = do putStrLn "Welcome to the arithmetic quiz!" forever quiz quiz = do e <- generate arbitrary putStrLn ("What is "++showExpr e++"?") answer <- readLn let correct = eval e if answer==correct then putStrLn "Yes, that is correct!" else putStrLn ("Sorry, the correct answer is: "++show correct) -------------------------------------------------------------------------------- -- | A representation of simple arithmetic expressions data Expr = Num Integer | Add Expr Expr | Mul Expr Expr deriving Show 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 -------------------------------------------------------------------------------- -- | Evaluate (compute the value of) an expression eval :: Expr -> Integer eval (Num n) = n eval (Add e1 e2) = eval e1 + eval e2 eval (Mul e1 e2) = eval e1 * eval e2 -------------------------------------------------------------------------------- -- | Showing expressions showExpr :: Expr -> String showExpr (Num n) = show n showExpr (Add e1 e2) = showExpr e1 ++ " + " ++ showExpr e2 showExpr (Mul e1 e2) = showFactor e1 ++ " * " ++ showFactor e2 showFactor :: Expr -> String showFactor e@(Add _ _) = "(" ++ showExpr e ++ ")" showFactor e = showExpr e --instance Show Expr where -------------------------------------------------------------------------------- -- * Generating arbitrary expressions -- | Random generator (with bad control of size) rExpr_v1 :: Gen Expr rExpr_v1 = oneof [do n <- choose (1,10) return (Num n), 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 :: Int -> Gen Expr rExpr 0 = do n <- choose (1,10) return (Num n) rExpr n = do op <- elements [Add,Mul] --l <- elements [0 .. n-1] l <- choose (0,n-1) let r = n-1 - l e1 <- rExpr l e2 <- rExpr r return (op e1 e2) instance Arbitrary Expr where arbitrary = do n <- choose (1,3) rExpr n