import Test.QuickCheck -- Data type for arithmetic expressions data Expr = Num Integer | Add Expr Expr | Mul Expr Expr deriving (Eq) 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)) -- Quiz: `eval e` gives the value of the expression `e` -- -- > eval ex1 -- 2 -- -- > eval ex2 -- 4 eval :: Expr -> Integer eval (Num n) = n eval (Add a b) = eval a + eval b eval (Mul a b) = eval a * eval b -- `showExpr e` shows the expression `e` as a string 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 e@(Add _ _) = "(" ++ showExpr e ++ ")" showFactor e = showExpr e instance Show Expr where show = showExpr questions :: IO () questions = do e <- generate (arbExpr 4) putStr $ "What is " ++ show e ++ "? " input <- getLine if input == show (eval e) then putStrLn "That's right!" else putStrLn "Wrong :(" putStrLn "" questions arbExpr :: Int -> Gen Expr arbExpr s = frequency [ (1, do n <- arbitrary return (Num n) ) , (s, do a <- arbExpr s' b <- arbExpr s' return (Add a b) ) , (s, do a <- arbExpr s' b <- arbExpr s' return (Mul a b) ) ] where s' = s `div` 2 instance Arbitrary Expr where arbitrary = sized arbExpr