Verschillende resultaten tussen interactieve en gecompileerde Haskell (Project Euler 20)

Ik doe probleem 20 op Project Euler - het vinden van de som van de cijfers van 100! (faculteit, geen enthousiasme).

Dit is het programma dat ik schreef:

import Data.Char

main = print $ sumOfDigits (product [1..100])

sumOfDigits :: Int -> Int
sumOfDigits n = sum $ map digitToInt (show n)

Ik heb het gecompileerd met ghc -o p20 p20.hs en het uitgevoerd, en kreeg alleen 0 op mijn opdrachtregel.

Verbaasd riep ik ghci aan en gaf de volgende regel weer:

sum $ map Data.Char.digitToInt (show (product [1..100]))

Dit leverde het juiste antwoord op. Waarom werkte de gecompileerde versie niet?

7

1 antwoord

De reden is de handtekening van het type

sumOfDigits :: Int -> Int
sumOfDigits n = sum $ map digitToInt (show n)

gebruik

sumOfDigits :: Integer -> Int

en je krijgt hetzelfde als in GHCi (wat je wilt).

Int is the type for machine word sized "ints" while, Integer is the type for mathematically correct, arbitrary precision Integers.

als je typt

:t product [1..100]

in GHCi krijg je zoiets als

product [1..100] :: (Enum a, Num a) => a

dat wil zeggen, voor ELK type met exemplaren van de klassen Enum en Numtype, kan product [1..100] een waarde van dat type zijn

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, becagebruikof roll over

product [1..100] :: Int

zal 0 retourneren

gezien dit, zou je kunnen denken

sum $ map Data.Char.digitToInt (show (product [1..100]))

would not type check, becagebruikit 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.

Om dezelfde reden, als u sumOfDigits NIET een expliciete typeaanduiding had gegeven, zou het gedaan hebben wat u wilt, aangezien het meest algemene type is

sumOfDigits :: Show a => a -> Int
15
toegevoegd