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))
  -- Example expressions: 2,  2+2,  (1+2)*3,  1+2*3
  -- What's the difference between 17 and `Num 17` ?



-- Quiz: `eval e` gives the value of the expression `e`
eval :: Expr -> Integer
eval (Num n)   = n
eval (Add a b) = eval a + eval b
eval (Mul a b) = eval a * eval b



-- socrative.com -> student login -> room: FP15



-- `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
  -- showExpr (Mul (Num 1) (Add (Num 2) (Num 3)))

showFactor :: Expr -> String
showFactor e@(Add _ _) = "(" ++ showExpr e ++ ")"
showFactor e           = showExpr e

-- Quiz: Which brackets are necessary?
--
--   1+(2+3) NO
--   1+(2*3) NO
--   1*(2+3) YES
--   1*(2*3) NO

instance Show Expr
  where
    show = showExpr



genExpr :: Int -> Gen Expr
genExpr s = frequency
    [ (1,  do n <- arbitrary
              return (Num n)
      )
    , (s,  do a <- genExpr (s `div` 2)
              b <- genExpr (s `div` 2)
              return (Add a b)
      )
    , (s,  do a <- genExpr (s `div` 2)
              b <- genExpr (s `div` 2)
              return (Mul a b)
      )
    ]

instance Arbitrary Expr
  where
    arbitrary = sized genExpr

-- Define questions
questions :: IO ()
questions = do
    e <- generate $ genExpr 5
    putStr ("What is " ++ show e ++ "? ")
    ans <- getLine
    if ans == show (eval e)
      then putStrLn "Right!"
      else putStrLn "Wrong!"
    questions


-- Fix "read: no parse"