7

私は Project Euler で問題 20 を実行しています - 100 の数字の合計を見つけます! (熱意ではなく階乗)。

これが私が書いたプログラムです:

import Data.Char

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

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

コマンドラインでのみ取得して、コンパイルしてghc -o p20 p20.hs実行しました。0

ghci困惑して、次の行を呼び出して実行しました。

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

これは正しい答えを返しました。コンパイルされたバージョンが機能しなかったのはなぜですか?

4

1 に答える 1

15

理由は型シグネチャです

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

使用する

sumOfDigits :: Integer -> Int

そして、GHCi と同じもの (あなたが望むもの) が得られます。

Intは機械語サイズの「int」Integerの型で、 は数学的に正しい任意精度の型ですIntegers

入力すると

:t product [1..100]

GHCiに入れると、次のようなものが得られます

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

つまり、Enum および Num 型クラスのインスタンスを持つ ANY 型product [1..100]の場合、その型の値になる可能性があります

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. たぶん、ロールオーバーのせい

product [1..100] :: Int

0 を返します

これを考えると、あなたは思うかもしれません

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

互換性のない解釈が複数ある可能性があるため、型チェックは行いません。しかし、計算機として使用できるようにするために、Haskell はデフォルトでIntegerこのような状況で使用するようになっているため、ユーザーの動作が説明されます。

同じ理由で、明示的な型署名を与えていない場合sumOfDigits、最も一般的な型は

sumOfDigits :: Show a => a -> Int
于 2012-06-24T00:52:47.740 に答える