I'm doing problem 20 on Project Euler - finding the sum of the digits of 100! (factorial, not enthusiasm).
Here is the program I wrote:
import Data.Char
main = print $ sumOfDigits (product [1..100])
sumOfDigits :: Int -> Int
sumOfDigits n = sum $ map digitToInt (show n)
I compiled it with ghc -o p20 p20.hs
and executed it, getting only 0
on my command line.
Puzzled, I invoked ghci
and ran the following line:
sum $ map Data.Char.digitToInt (show (product [1..100]))
This returned the correct answer. Why didn't the compiled version work?
The reason is the type signature
sumOfDigits :: Int -> Int
sumOfDigits n = sum $ map digitToInt (show n)
use
sumOfDigits :: Integer -> Int
and you will get the same thing as in GHCi (what you want).
Int
is the type for machine word sized "ints" while, Integer
is the type for mathematically correct, arbitrary precision Integers
.
if you type
:t product [1..100]
into GHCi you will get something like
product [1..100] :: (Enum a, Num a) => a
that is, for ANY type that has instances of the Enum and Num type classes, product [1..100]
could be a value of that type
product [1..100] :: Integer
should return 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 which is far bigger than your machine is likely to be able to represent as a word on your machine. Probably, because of roll over
product [1..100] :: Int
will return 0
given this, you might think
sum $ map Data.Char.digitToInt (show (product [1..100]))
would not type check, because it has multiple possible incompatible interpretations. But, in order to be usable as a calculator, Haskell defaults to using Integer
in situations like this, thus explaining your behavior.
For the same reason, if you had NOT given sumOfDigits
an explicit type signature it would have done what you want, since the most general type is
sumOfDigits :: Show a => a -> Int
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With