2012-06-24 10 views
7

Ich mache Problem 20 auf Projekt Euler - Finden der Summe der Ziffern von 100! (Fakultät, nicht Begeisterung).Verschiedene Ergebnisse zwischen interaktiven und kompilierten Haskell (Projekt Euler 20)

Hier ist das Programm schrieb ich:

import Data.Char 

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

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

ich es mit ghc -o p20 p20.hs kompiliert und ausgeführt es, immer nur 0 auf meine Befehlszeile.

Verwirrt aufgerufen ich ghci und lief die folgende Zeile:

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

dies die richtige Antwort zurückgegeben. Warum funktioniert die kompilierte Version nicht?

Antwort

15

Der Grund dafür ist die Art Unterschrift

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

Verwendung

sumOfDigits :: Integer -> Int 

und Sie werden das gleiche wie in GHCi bekommen (was du willst).

Int ist der Typ für Maschinenwortgröße "ints", während Integer der Typ für mathematisch korrekte, beliebige Genauigkeit ist Integers.

wenn Sie

:t product [1..100] 

in GHCi Typ sind Sie so etwas wie

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

erhalten, die für jede Art ist, die Instanzen der Enum und Num Typklassen hat, product [1..100] ein Wert sein könnte dieses Typs

product [1..100] :: Integer 

sollte 93326215443944152681699238856266700490715 zurückkehren 968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 das ist viel größer als Ihre Maschine ist wahrscheinlich in der Lage, als ein Wort auf Ihrer Maschine zu repräsentieren. Wahrscheinlich wegen der Rolle über

product [1..100] :: Int 

0 zurück

dies gegeben, könnte man denken

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

überprüfen würde nicht geben, weil es mehrere mögliche Interpretationen nicht kompatibel ist. Um jedoch als Taschenrechner verwendet werden zu können, verwendet Haskell in solchen Situationen standardmäßig Integer und erklärt so Ihr Verhalten.

Aus dem gleichen Grund, wenn Sie NICHT sumOfDigits eine explizite Art Unterschrift gegeben hatte es getan hätte, was Sie wollen, da die allgemeinste Art

sumOfDigits :: Show a => a -> Int 
ist