2015-02-26 19:50:12 +01:00
|
|
|
{-# LANGUAGE ViewPatterns #-}
|
|
|
|
|
|
|
|
import Data.List
|
2015-02-28 00:27:52 +01:00
|
|
|
import Data.Maybe
|
2015-02-26 23:12:56 +01:00
|
|
|
import Text.Read
|
2015-02-27 00:58:54 +01:00
|
|
|
import Text.Printf
|
2015-02-26 23:12:56 +01:00
|
|
|
import Control.Monad
|
2015-02-28 00:27:52 +01:00
|
|
|
import System.Console.Readline
|
2015-02-26 19:50:12 +01:00
|
|
|
|
|
|
|
main :: IO ()
|
2015-02-28 00:27:52 +01:00
|
|
|
main = do
|
|
|
|
line <- readline "ꟼ "
|
|
|
|
case fromMaybe "" line of
|
|
|
|
"" -> main
|
|
|
|
"q" -> return ()
|
|
|
|
exp -> do
|
|
|
|
putStrLn $ result (rpn exp) ++ "\n"
|
|
|
|
addHistory exp
|
|
|
|
main
|
2015-02-26 19:50:12 +01:00
|
|
|
|
2015-02-27 00:58:54 +01:00
|
|
|
|
|
|
|
-- Pretty print RPN result/errors
|
|
|
|
result :: Either String Double -> String
|
|
|
|
result (Left err) = "Ꞥ∘ " ++ err
|
2015-02-28 00:27:52 +01:00
|
|
|
result (Right x) = printf format x where
|
|
|
|
format | ceiling x == floor x = "∘ %.0f"
|
|
|
|
| otherwise = "∘ %.10f"
|
2015-02-27 00:58:54 +01:00
|
|
|
|
|
|
|
|
|
|
|
-- Solve a RPN expression
|
2015-02-26 23:12:56 +01:00
|
|
|
rpn :: String -> Either String Double
|
2015-02-27 00:58:54 +01:00
|
|
|
rpn = foldM parse [] . words >=> return . head where
|
|
|
|
parse (y:x:xs) (flip lookup dyad -> Just f) = Right (f x y : xs)
|
|
|
|
parse (x:xs) (flip lookup monad -> Just f) = Right (f x : xs)
|
|
|
|
parse xs (flip lookup nilad -> Just k) = Right (k : xs)
|
2015-02-27 14:04:05 +01:00
|
|
|
parse xs (readMaybe -> Just x) = Right (x : xs)
|
2015-02-27 23:13:22 +01:00
|
|
|
parse _ _ = Left "syntax error"
|
2015-02-27 00:58:54 +01:00
|
|
|
|
2015-02-26 19:50:12 +01:00
|
|
|
|
|
|
|
-- dyadic functions
|
|
|
|
dyad = [ ("+", (+))
|
|
|
|
, ("-", (-))
|
|
|
|
, ("*", (*))
|
|
|
|
, ("/", (/))
|
|
|
|
, ("^", (**)) ]
|
|
|
|
|
|
|
|
-- monadic functions
|
|
|
|
monad = [ ("sin" , sin )
|
|
|
|
, ("asin" , asin)
|
|
|
|
, ("cos" , cos )
|
|
|
|
, ("acos" , acos)
|
|
|
|
, ("tan" , tan )
|
|
|
|
, ("atan" , atan)
|
|
|
|
, ("ln" , log )
|
|
|
|
, ("sqrt" , sqrt)
|
|
|
|
, ("sgn" , signum)
|
|
|
|
, ("abs" , abs)
|
|
|
|
, ("floor", fromIntegral . floor)
|
|
|
|
, ("ceil" , fromIntegral . ceiling) ]
|
|
|
|
|
|
|
|
-- niladic functions
|
|
|
|
nilad = [ ("pi" , pi)
|
|
|
|
, ("e" , exp 1)
|
|
|
|
, ("phi", (1 + sqrt 5)/2) ]
|