packages feed

hascal 1.4.1 → 1.4.2

raw patch · 3 files changed

+67/−38 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Hascal: eval :: (Read t, RealFloat t) => [(Char, Complex t -> Complex t -> Complex t)] -> String -> Maybe (Complex t)
+ Hascal: eval :: (Read t, RealFloat t) => [(Char, Complex t -> Complex t -> Complex t)] -> String -> Either String (Complex t)
- Hascal: hascal :: (Read t, RealFloat t) => String -> Maybe (Complex t)
+ Hascal: hascal :: (Read t, RealFloat t) => String -> Either String (Complex t)

Files

Hascal.hs view
@@ -3,7 +3,7 @@ --  -- Also, its source code is a nice example for a minimalistic Haskell project. -- --- Some examples for the usage of the command-line program:+-- Some examples for the usage of the command-line program (using bash): --  -- >>> hascal 1+2 -- 3.0@@ -17,7 +17,7 @@ -- >>> hascal _1 ^ 0.5 -- !1.0 -- --- And as you can see, negative numbers are preceded by a underscore.+-- And as you can see, negative numbers are preceded by an underscore. --  -- Although hascal itself doesn't understand brackets, you can use your shell -- to get that functionality, like this (using bash):@@ -26,7 +26,7 @@ -- -1.0 --  -- Speaking of shells, you should consider that your shell might extend an--- asterisk (*) to the files at the current directory, like here:+-- asterisk (*) to the files at the current directory, like this: --  -- >>> echo * -- _darcs dist hascal.cabal Hascal.hs LICENSE Main.hs README.org Setup.hs@@ -41,7 +41,12 @@ -- >>> hascal 1*2 -- 2 -- --- Yeah, that's it. Hascal is really minimalistic.+-- Or, you could do:+-- +-- >>> hascal '1*2'+-- 2+-- +-- Yeah, that's pretty much it. Hascal is really minimalistic. -- And I'm not planning to extend it much. module Hascal (   -- * Operators@@ -63,8 +68,7 @@  -- |'operators' is the default list of operators. -- --- An operator consists of one character and a function with of type--- @Number -> Number -> Number@.+-- An operator consists of one character and a function. --  -- 'operators' includes: -- @@ -99,13 +103,19 @@ calc :: (Read t, RealFloat t)      => [(Char, Complex t -> Complex t -> Complex t)]      -> String-     -> Maybe (Complex t)-calc []          a = readNumber a-calc l@((c,f):s) a | z /= ""   = case (calc l y,calc l z) of-                                   (Just n,Just m) -> Just (f m n)-                                   _               -> Nothing-                   | otherwise = calc s a-                   where (y,z) = second (drop 1) $ break (==c) a+     -> Either String (Complex t)+calc []          a+    = readNumber a+calc l@((c,f):s) a+    | z /= ""+    = case (calc l y,calc l z) of+        (Right n,Right m) -> Right (f m n)+        (Left  n,_      ) -> Left n+        (_      ,Left  m) -> Left m+    | otherwise+    = calc s a+  where+    (y,z) = second (drop 1) $ break (==c) a   -- |'eval' gets a list of operators and a string containing a mathematical@@ -114,36 +124,45 @@ eval :: (Read t, RealFloat t)      => [(Char, Complex t -> Complex t -> Complex t)] -- ^ list of operators      -> String                                        -- ^ string containing term-     -> Maybe (Complex t)                             -- ^ just result, or nothing+     -> Either String (Complex t)                     -- ^ just result, or nothing eval = (. reverse) . calc  -readNumber :: (Read t, RealFloat t) => String -> Maybe (Complex t)-readNumber ('!':s) = ((0:+1)*) <$> findOrRead s-readNumber ('_':s) =    negate <$> findOrRead s-readNumber      s  =               findOrRead s+-- Respects preceding exclamation marks and underscores before a number+readNumber :: (Read t, RealFloat t) => String -> Either String (Complex t)+readNumber x = case reverse x of+                 ('!':s) -> ((0:+1)*) <$> findOrRead s+                 ('_':s) ->    negate <$> findOrRead s+                 ('-':s) -> Left ("Error at \"-" +++                                  s +++                                  "\".\n\nTo denote negative numbers, " +++                                  "use a preceding underscore instead.")+                 s       ->               findOrRead s  -findOrRead :: (Read t, Floating t) => String -> Maybe (Complex t)-findOrRead a = let s = reverse a in-               maybe (maybeRead s) (Just . snd) $ find ((==s) . fst)+-- Checks whether the string is readable as a mathematical constant before+-- trying to read it as a number+findOrRead :: (Read t, Floating t) => String -> Either String (Complex t)+findOrRead s = maybe (maybeRead s) (Right . snd) $ find ((==s) . fst)                [("pi",pi   :+0)                ,("e" ,exp 1:+0)                ,("i" ,0    :+1)                ]  -maybeRead :: (Read t, Num t) => String -> Maybe (Complex t)-maybeRead s | any (null . snd) (reads s :: [(Double,String)])-            = Just (read s:+0)-            | otherwise-            = Nothing+-- Reads numbers+maybeRead :: (Read t, Num t) => String -> Either String (Complex t)+maybeRead s+    | any (null . snd) (reads s :: [(Double,String)])+    = Right (read s:+0)+    | otherwise+    = Left ("Error at \"" ++ s ++ "\".")   -- |'hascal' is the default evaluator: --  -- @ hascal = 'eval' 'operators' @-hascal :: (Read t, RealFloat t) => String -> Maybe (Complex t)+hascal :: (Read t, RealFloat t) => String -> Either String (Complex t) hascal = eval operators  @@ -151,5 +170,5 @@ -- E.g., it doesn't show the real or imaginary part of the number if it's @0@. prettyPrint :: (Show t, RealFloat t) => Complex t -> String prettyPrint (r:+0) = show r-prettyPrint (0:+i) = '!' : show i-prettyPrint (r:+i) = show r ++ " + !" ++ show i+prettyPrint (0:+i) = show i ++ "*i"+prettyPrint (r:+i) = show r ++ " + " ++ show i ++ "*i"
Main.hs view
@@ -9,6 +9,10 @@   main :: IO ()-main = getArgs >>= liftM2 unless null-       (putStrLn . maybe "Error. :(" prettyPrint .-        (hascal :: String -> Maybe (Complex CReal)) . concat)+main = do+  args <- getArgs+  unless (null args) $+    putStrLn $+      either id prettyPrint $+        (hascal :: String -> Either String (Complex CReal)) $+          concat args
hascal.cabal view
@@ -1,10 +1,16 @@ name:          hascal-version:       1.4.1+version:       1.4.2 synopsis:      A minimalistic but extensible and precise calculator-description:   Hascal is a minimalistic calculator with infix-operations-               supporting addition, subtraction, division, multiplication,-               exponentiation and logarithming.-               Futhermore, it's easy to add custom operators.+description:   Hascal is both a simple but extendable calculator library for+               Haskell as well as a command-line program using this library.+               .+               Hascal supports addition, subtraction, multiplication, division,+               exponentiation, and logarithm, while it's easy to add custom+               operators.+               .+               Hascal also supports complex numbers. Hascal can work at an+               arbitrary precision. However, Hascal does not support+               parenthesis. stability:     provisional category:      Math, Console, Tools, Utility, Utils, Parsing homepage:      http://darcsden.com/mekeor/hascal@@ -26,7 +32,7 @@  source-repository head   type:     git-  location: git://github.com/MekeorMelire/hascal.git+  location: git://github.com/mekeor/hascal.git   test-suite test