2012-06-24 11 views
7

Sto facendo il problema 20 su Project Euler - trovare la somma delle cifre di 100! (fattoriale, non entusiasmo).Risultati diversi tra Haskell interattivo e compilato (Project Euler 20)

Ecco il programma che ho scritto:

import Data.Char 

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

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

ho compilato con ghc -o p20 p20.hs ed eseguito, ottenendo solo 0 sulla mia linea di comando.

Perplesso, ho invocato ghci e corse la seguente riga:

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

Questa restituito la risposta corretta. Perché la versione compilata non funziona?

risposta

15

Il motivo è il tipo di firma

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

uso

sumOfDigits :: Integer -> Int 

e si otterrà la stessa cosa come in GHCi (quello che volete).

Int è il tipo di parola della macchina "int" dimensionate mentre, Integer è il tipo per matematicamente corretto, precisione arbitraria Integers.

se si digita

:t product [1..100] 

in GHCi si ottiene qualcosa di simile

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

che è, per qualsiasi tipo che ha istanze delle classi tipo enum e Num, product [1..100] potrebbe essere un valore di quel tipo

product [1..100] :: Integer 

dovrebbe restituire 93326215443944152681699238856266700490715 968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 che è molto più grande di quanto la tua macchina sia in grado di rappresentare come una parola sulla tua macchina. Probabilmente, a causa del ribaltamento

product [1..100] :: Int 

tornerà 0

Detto questo, si potrebbe pensare

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

non avrebbero digitare controllare, perché ha molteplici possibili interpretazioni incompatibili. Tuttavia, per essere utilizzabile come calcolatrice, Haskell utilizza automaticamente lo Integer in situazioni come questa, spiegando così il tuo comportamento.

Per lo stesso motivo, se non ti avessi dato sumOfDigits una firma esplicita del tipo che avrebbe fatto ciò che si vuole, dal momento che il tipo più generale è

sumOfDigits :: Show a => a -> Int 
Problemi correlati