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 +48/−29
- Main.hs +7/−3
- hascal.cabal +12/−6
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