From c543eebfcbd92bb261003dbfd658487b59362a5b Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Sun, 20 Aug 2017 13:03:37 +0200 Subject: Factorial: Use `Integer` instead of `Int` for bigger numbers The `Integer` type has arbitrary precision. This is why the function was working fine in GCHi but overflowing when I was testing the bot. Use `Integer` to get the real values we want. https://stackoverflow.com/questions/36355757/large-numbers-become-negative-in-haskell Also add a little extra error handling to deal with unexpected numbers. Now that I think about it, the regex parser isn't going to handle negative numbers, so we're good on that front. Set an upper bound so we don't end up spending a lot of time trying to calculate numbers and potentially segfault if huge numbers are given. --- src/Plugin/Factorial.hs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Plugin/Factorial.hs b/src/Plugin/Factorial.hs index 692d20f..97730de 100644 --- a/src/Plugin/Factorial.hs +++ b/src/Plugin/Factorial.hs @@ -23,7 +23,14 @@ factorialAction message = do [] -> return $ Left "I didn't understand" (m:_) -> do let number = last m - return $ Right $ showt $ calculate $ (read number :: Int) + return $ Right $ result (read number :: Integer) + where + result n = case calculate n of + Nothing -> "Input is too large." + Just n -> showt n -calculate :: (Integral a) => a -> a -calculate n = product [1..n] +calculate :: Integer -> Maybe Integer +calculate n + | n <= 0 = Just 0 + | n <= 35000 = Just $ product [1..n] + | otherwise = Nothing -- cgit v1.2.3