Created
November 18, 2018 00:46
-
-
Save Solonarv/79799f9aaf4746620f0188fe7d34d08b to your computer and use it in GitHub Desktop.
Simple RPN calculator. Takes the program from command-line arguments.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import System.Environment (getArgs) | |
import Control.Applicative | |
import Data.Maybe | |
import Text.Read | |
main :: IO () | |
main = do | |
program <- parse . unwords <$> getArgs | |
putStrLn . unwords . reverse . fmap show $ eval program | |
type Val = Integer | |
type Op = Val -> Val -> Val | |
data Instr = Push Val | Exec Op | |
parse :: String -> [Instr] | |
parse = mapMaybe parseWord . words | |
where | |
parseWord w = (Push <$> readMaybe w) <|> (Exec <$> lookup w ops) | |
ops :: [(String, Op)] | |
ops = | |
[ ("+", (+)) | |
, ("-", (-)) | |
, ("*", (*)) | |
] | |
eval :: [Instr] -> [Val] | |
eval prog = eval' prog [] | |
eval' :: [Instr] -> [Val] -> [Val] | |
eval' [] vs = vs | |
eval' (i:is) vs = case i of | |
Push v -> eval' is (v:vs) | |
Exec op -> case vs of | |
x:y:rest -> eval' is ((op x y):rest) | |
_ -> error "Not enough arguments!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment