import Maybe
import Lang

{- Haskell ma specialni tridu Monad pro monady
     bind ... >>=
     return ... return
     err ... fail
   a specialni do notaci

     do x
        y

   je ekvivalentni

     x >>= \_ -> do y

   do v <- x
      y

   je ekvivalentni

     x >>= \v -> do y

   do x  je ekvivalentni x -}

data Result x = Chyba String | Hodnota x deriving (Show)
instance Monad Result where
  Chyba s >>=  _ = Chyba s
  Hodnota a >>= f = f a
  return x = Hodnota x
  fail s = Chyba s

eval::Monad m => Expr->m Integer
eval (Plus e1 e2) = 
  do
   r1 <- eval e1
   r2 <- eval e2
   return (r1 + r2)
eval (Minus e1 e2) =
  do
   r1 <- eval e1
   r2 <- eval e2
   return (r1 - r2)
eval (Mul e1 e2) = 
  do
   r1 <- eval e1
   r2 <- eval e2
   return (r1 * r2)
eval (Div e1 e2) =
  do
   r1 <- eval e1
   r2 <- eval e2
   if r2 == 0 then fail "Deleni nulou" else return (r1 `div` r2)
eval (Mod e1 e2) =
  do
   r1 <- eval e1
   r2 <- eval e2 
   if r2 == 0 then fail "Deleni nulou" else return (r1 `mod` r2)
eval (Negate e) =
  do
   r <- eval e
   return (negate r)
eval (Num n) = return n
