2016-08-31 3 views
0

Я начинаю изучать Haskell, и я не понимаю, что происходит: у меня есть очень простой код:печати очень большие цифры

import System.IO 
import Control.Monad 

fact n = product [1..n] 

main :: IO() 
main = do 
    input_line <- getLine 
    let m = read input_line :: Int 
    print (fact m) 
    return() 

В GHCI, когда я пытаюсь

*Main> :load "fact.hs" 
[1 of 1] Compiling Main    (fact.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> main 
4500 
0 

но

*Main> fact 4500 
2274299510944531831673..... 

Что мне не хватает? Спасибо за любые объяснения.

+5

'Int' - это ограниченный размер. Ghci не выполняет функции Unger 'Interger'. –

+1

Некоторые советы по стилю: ** 1. ** 'return()' обычно не требуется ** 2. ** большинство Haskellers имеют небольшое предпочтение 'print $ fact m' over' print (fact m) '** 3. ** вы всегда должны писать сигнатуры типов для определения верхнего уровня. – leftaroundabout

+0

Хорошо, спасибо за эти советы – joel76

ответ

7

Тип fact: Num a => a -> a. В вашем main вы применяете его к m, который вы объявили Int. Таким образом, результат fact будет Int, и все расчеты между ними будут выполнены с использованием Int s. Int s - целые числа фиксированной ширины и не могут представлять числа, большие, вызывая переполнение и, следовательно, неправильные результаты.

С вашей второй попытки вы применяете fact к 4500 без указания какого типа вы хотите 4500 быть. В подобных случаях Haskell использует тип номера по умолчанию, который равен Integer. В отличие от Int, Integer может представлять целые числа любого размера, поэтому код просто работает.

Если вы сделали fact 4500 :: Int, вы получите тот же неправильный результат, что и в первый раз. Аналогично, если вы используете :: Integer в своем main вместо Int (или оставьте его, поэтому по умолчанию используется снова¹), вы получите правильный результат.


¹ Обратите внимание, что это приведет к предупреждению. Явно аннотируя тип вместо того, чтобы полагаться на правила дефолта, обычно предпочтительнее вне GHCi или небольших тестовых программ.

+0

Если вы оставили аннотацию какого-либо типа в 'main', вы получите' Integer' по тем же правилам по умолчанию. – Alec

+0

@Alec Правильно, я добавил это. – sepp2k

+0

Большое спасибо. Я начинаю понимать целые числа в Haskell. Я попробовал Int64 с тем же результатом. Я думал, что Int64 будет достаточно большим ... – joel76