{-# LANGUAGE NoMonomorphismRestriction #-} import Control.Monad import Control.Applicative import Data.Complex import Foreign.C.Types calcRPN fs s = do [result] <- foldM f [] $ words s return result where f = foldr (\f g xs s -> f xs s <|> g xs s) push fs push xs s = (:xs) <$> case reads s of {[(x, "")] -> Just x; _ -> Nothing} infixMaybe op a (y:x:xs) b | a == b = Just $ x `op` y : xs | otherwise = Nothing infixMaybe _ _ _ _ = Nothing add = infixMaybe (+) "+" sub = infixMaybe (-) "-" mul = infixMaybe (*) "*" fdiv = infixMaybe (/) "/" extension zs@(x:xs) "sum" = Just [sum zs] extension (x:xs) "exp" = Just $ exp x : xs extension _ _ = Nothing --ndiv = infixMaybe div "/" -- might raise the divide-by-zero exception ndiv (y:x:xs) "/" | y /= 0 = Just $ x `div` y : xs | otherwise = Nothing ndiv _ _ = Nothing main = do print $ calcRPN [add, sub, mul, fdiv] "3 19 + -2 /" print $ calcRPN [add, sub, mul, fdiv] "1 2 3" print $ calcRPN [add, sub, mul, fdiv, extension] "5 4 - exp 3 -2 1 sum" print $ calcRPN [add, sub, mul, fdiv] "5 2.5 +" print $ calcRPN [add, sub, mul, ndiv] "5 2.5 +" print $ calcRPN [add, sub, mul, ndiv] "5 2 /" print $ calcRPN [add, sub, mul, ndiv] "0 0 /" print $ (calcRPN [add, sub, mul, ndiv] "1 2 -" :: Maybe CUInt) print $ (calcRPN [add, sub, mul, fdiv, extension] :: String -> Maybe (Complex Double)) "1:+1 3:+(-2) + exp"