Меня смущает поведение следующего:
import Data.Int
import Data.Array.ST
import Control.Monad.ST
{-# INLINE fib #-}
fib _ 0 = return 0
fib _ 1 = return 1
fib c n = do
f1 <- memo c (fib c) (n-1)
f2 <- memo c (fib c) (n-2)
return (f1+f2)
newtype C a = C a
{-# INLINE memo #-}
memo (C a) f k = do
e <- readArray a k
if e == (-1)
then do
v <- f k
writeArray a k v
return v
else return e
evalFib :: Int -> Int
evalFib n = runST $ do
a <- newArray (0,n) (-1) :: ST s (STUArray s Int Int)
fib (C a) n
main = print $ evalFib 120000
Когда скомпилировано с -O2
, он переполняет стек (показывает 20M используемой памяти). Запутанная часть состоит в том, что она работает нормально (без и используемой памяти 9M), если выполнено одно из следующих изменений:
-
Int64
используется вместоInt
: (даваяevalFib :: Int64 -> Int
иSTUArray s Int64 Int
). Фактически любыеInt*
(Int32
,Int16
и т.д.) Будут выполнять трюк, а такжеWord
илиWord*
; -
newtype C a
удаляется из изображения; -
data C a = C !a
используется вместоnewtype
Я пытаюсь понять это поведение: это ошибка в модуле GHC/array (он показывает одинаковое поведение в 7.4.2
и 7.6.2
), или он должен работать таким образом?
PS Самое смешное, что, когда я пытаюсь скомпилировать его с помощью ghc array.hs -O2 -fext-core
, чтобы увидеть различия в ядре, выпущенные как версии GHC, терпят неудачу с помощью "ghc: panic!" ( "невозможное" произошло) ". Не повезло и здесь.