module EvalRPN (evalRPN) where
import Control.Monad.State
{-
Function evalRPN evaluates an expression given
in the reversed polish notation (RPN, postfix notation):
evalRPN "2 3 +" ==> 5 (== "2 + 3")
evalRPN "2 3 4 + *" ==> 14 (== 2 * (3 + 4))
-}
type Stack = [Integer]
type EvalM = State Stack
push :: Integer -> EvalM ()
push x = modify (x:)
pop :: EvalM Integer
pop = do
xs <- get
put (tail xs)
pure (head xs)
evalRPN :: String -> Integer
evalRPN expr = evalState evalRPN' []
where
evalRPN' = traverse step (words expr) >> pop
step "+" = processTops (+)
step "*" = processTops (*)
step "-" = processTops (-)
step t = push (read t)
processTops op = flip op <$> pop <*> pop >>= push