-- Slide 64

data Expr a = Val a | Inc (Expr a) | Dec (Expr a) | Inv (Expr a) | Neg (Expr a)

evaluate::(Fractional a)=>Expr a -> a
evaluate (Val x) = x
evaluate (Inc e) = 1 + evaluate e
evaluate (Dec e) = (evaluate e) - 1
evaluate (Inv e) = 1 / (evaluate e)
evaluate (Neg e) = negate (evaluate e)

-- data Maybe a = Nothing | Just a

isZero::(Num a, Eq a)=>Maybe a -> Bool
isZero m = case m of 
	Nothing -> True
	Just x -> if x == 0 then True else False

mfmap::(Fractional a) => (a -> b) -> Maybe a -> Maybe b
mfmap f m = case m of
	Nothing -> Nothing
	Just x -> Just (f x)

safeval::(Fractional a, Eq a) => Expr a -> Maybe a
safeval (Val x) = Just x
safeval (Inc e) = mfmap (+ 1) (safeval e)
safeval (Dec e) = mfmap (subtract 1) (safeval e)
safeval (Inv e) = let v = safeval e in if isZero v then Nothing else mfmap (1 /) v
safeval (Neg e) = mfmap negate (safeval e)