2013-01-20 25 views
6
GHCi, version 7.4.2: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> let fac 0 = 1 
Prelude> let fac n = product [1..n] 
Prelude> fac 100000 
Segmentation fault: 11 

Czy ktoś ma pojęcie, dlaczego tak się dzieje?Błąd segmentacji haskell z silnikiem

fac 10000 działa

działa na OS X 10.8.2

Hmm, tak ładuje z pliku:

fac :: Integer -> Integer 
fac 0 = 1 
fac n = product [1..n] 

przebiegów.

również interesujące jest to, że za pomocą

fac :: Int -> Int

powraca 0 dla fac 100000. Spodziewałbym się (tak jak JohnL) błędu.

this site wspomina:

  • Dokładniej SegmentationFault jest sposobem językiem typu niebezpieczne zaklęcia DoesNotUnderstand. W typowo statycznych językach, takich jak Haskell, nie powinieneś widzieć segfaultów.

jest to coś zrobić z monady IO?

+0

Jeśli zamierzasz przegłosować, proszę przynajmniej wyjaśnić, dlaczego. – beoliver

+3

Nie jestem pewien, czy jest wystarczająco dużo informacji, aby zdiagnozować problem. To jest zdecydowanie w kategorii "nigdy nie powinno się zdarzyć", więc coś bardzo dziwnego dzieje się z twoim systemem. –

+0

'fac 100000 :: Integer' daje tutaj 456574 cyfry na os x. 'fax 100000 :: Int' to' 0 :: Int', ponieważ, mówiąc krótko, jest to wielokrotność 2^32 (lub 2^64). – applicative

Odpowiedz

2

Z szybkiego testu wynika, że ​​jest on spowodowany faktem, że product nie jest ścisły, a łańcuch uderzeń powoduje usterkę.

W preludium, product jest zdefiniowany jako:

product = foldl (*) 1 

Jeśli w ghci, zamiast tego zdefiniować jako:

> :m + Data.List 
> let product = foldl' (*) 1 
> let fac n = product [1..n] 

Wtedy powinno działać. Podejrzewam, że podając sygnaturę typu, może nastąpić optymalizacja, której nie ma w innych przypadkach ... ale nie zagłębił się w nią.

Przy okazji nie potrzebujesz linii let fac 0 = 1.

+0

Przekleństwo zła' foldl' !!! – beoliver

1

nadając jej rodzajem podpisu

fac :: Integer -> Integer

będzie działać. Nie do końca rozumiem dlaczego.

+0

Czy to działa, jeśli podasz sygnaturę typu "fac :: Int -> Int"? Podejrzewam, że również będzie to segfault. –

+0

@JohnL przy użyciu 'fac :: Int -> Int' zwraca' 0' dla 'fac 100000' – beoliver

Powiązane problemy