hsilop/hsilop.hs

64 lines
1.7 KiB
Haskell
Raw Normal View History

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-03-14 20:31:16 +01:00
import System.Console.Haskeline
2015-02-26 19:50:12 +01:00
main :: IO ()
2015-03-14 20:31:16 +01:00
main = runInputT defaultSettings repl
repl :: InputT IO ()
repl = do
line <- getInputLine ""
2015-02-28 00:50:25 +01:00
case fromMaybe "" line of
"q" -> return ()
2015-03-14 20:31:16 +01:00
"" -> outputStrLn "" >> repl
exp -> outputStrLn (result (rpn exp) ++ "\n") >> repl
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) ]