--------------------------------------------------------------------------------- -- An evalutor for arithmetic expressions -- A representation for arithmetic expressions data Exp = Num Int | Add Exp Exp | Sub Exp Exp | Mul Exp Exp | Div Exp Exp deriving Show -- 3 + 4*5 --> Just 23 exp1 :: Exp exp1 = Add (Num 3) (Mul (Num 4) (Num 5)) -- (2*3) + 6 / (2 - 2) --> undefiniert / Nothing exp2 :: Exp exp2 = Add (Mul (Num 2) (Num 3)) (Div (Num 6) (Sub (Num 2) (Num 2))) -- The evaluator: evalAp :: Exp -> Maybe Int evalAp (Num n) = Just n evalAp (Add e1 e2) = (+) <$> evalAp e1 <*> evalAp e2 evalAp (Sub e1 e2) = (-) <$> evalAp e1 <*> evalAp e2 evalAp (Mul e1 e2) = (*) <$> evalAp e1 <*> evalAp e2 evalAp (Div e1 e2) = mdiv (evalAp e1) (evalAp e2) where mdiv Nothing _ = Nothing mdiv (Just _) Nothing = Nothing mdiv (Just m) (Just n) = safeDiv m n safeDiv :: Int -> Int -> Maybe Int safeDiv m n | n == 0 = Nothing | otherwise = Just (m `div` n) processMaybe :: Maybe a -> (a -> Maybe b) -> Maybe b processMaybe Nothing _ = Nothing processMaybe (Just x) fn = fn x eval :: Exp -> Maybe Int eval (Num n) = Just n eval (Add e1 e2) = (+) <$> eval e1 <*> eval e2 eval (Sub e1 e2) = (-) <$> eval e1 <*> eval e2 eval (Mul e1 e2) = (*) <$> eval e1 <*> eval e2 eval (Div e1 e2) = processMaybe (eval e1) (\m -> processMaybe (eval e2) (\n -> safeDiv m n)) {- class Applicative m => Monad m where return :: a -> m a return = pure (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b a >> b = a >>= (\_ -> b) instance Monad Maybe where return = pure (>>=) = processMaybe -} -- Monadic interpreter for arithmetic expressions evalM :: Exp -> Maybe Int evalM (Num n) = pure n -- instead of Just n evalM (Add e1 e2) = (+) <$> evalM e1 <*> evalM e2 evalM (Sub e1 e2) = (-) <$> evalM e1 <*> evalM e2 evalM (Mul e1 e2) = (*) <$> evalM e1 <*> evalM e2 evalM (Div e1 e2) = do m <- evalM e1 n <- evalM e2 (safeDiv m n)