-- data MyList a = Cons a (MyList a)
-- | Nil
-- Cons (1, Cons (2, Nil))
-- f (1, f(2, base))
-- foldList :: (a -> b -> b) -> b -> MyList a -> b
-- foldList _ base (Nil n) = base n
data Exp = EInt Int
| EAdd Exp Exp
| EMin Exp Exp
| EMul Exp Exp
deriving (Show, Eq)
-- EInt 5 => rInt 5
-- EAdd (EInt 5) (EInt 4) => rAdd (rInt 5) (rInt 4)
foldE :: (Int -> a) -> (a -> a -> a) -> (a -> a -> a) -> (a -> a -> a) -> Exp -> a
foldE rInt _ _ _ (EInt n) = rInt n
foldE a rAdd b c (EAdd e1 e2) = rAdd (foldE a rAdd b c e1) (foldE a rAdd b c e2)
foldE a b rMin c (EMin e1 e2) = rMin (foldE a b rMin c e1) (foldE a b rMin c e2)
foldE a b c rMul (EMul e1 e2) = rMul (foldE a b c rMul e1) (foldE a b c rMul e2)
eval :: Exp -> Int
eval e = foldE id (-) (+) (*) e
-- EInt 5 => rInt 5 => 5
-- (1 - 2) + 3 * (4 - 5) = -24
-- (1 + 2) - 3 * (4 + 5)
testvalue = EMin (EAdd (EInt 1) (EInt 2)) (EMul (EInt 3) (EAdd (EInt 4) (EInt 5)))
main = print $ eval testvalue