2
我在Haskell寫了一個簡單的(情節較輕)素數生成器,具有相互遞歸定義,生成素數和確定數量的primeness:基於類型的具體性重構懶惰列表?
primes :: (Integral a) => [a]
primes = 2 : filter isPrime [3, 5..]
isPrime :: (Integral a) => a -> Bool
isPrime m = all (indiv m) (takeWhile (<= (intSqrt m)) primes)
intSqrt :: (Integral a) => a -> a
intSqrt 1 = 1
intSqrt n = div (m + (div (n - 1) m)) 2
where m = intSqrt (n - 1)
indiv :: (Integral a) => a -> a -> Bool
indiv m n = rem m n /= 0
我注意到這是重建子列表已經產生的每參考撇到primes
:
*Main> take 200 primes
[2,3,5,7, ..., 1223]
(2.70 secs, 446142856 bytes)
*Main> take 200 primes
[2,3,5,7, ..., 1223]
(2.49 secs, 445803544 bytes)
但是,當我改變類型註釋用一個具體的整數類型,如
primes :: [Integer]
isPrime :: Integer -> Bool
每一個素只生成一次:
*Main> :r
[1 of 1] Compiling Main (Primes.hs, interpreted)
Ok, modules loaded: Main.
*Main> take 200 primes
[2,3,5,7, ..., 1223]
(2.15 secs, 378377848 bytes)
*Main> take 200 primes
[2,3,5,7, ..., 1223]
(0.01 secs, 1626984 bytes)
似乎很想我。這有什麼特別的原因?
這種令人驚訝的缺乏共享,與「多態常量」發生時計算是[單態限制]引入(http://www.haskell.org/haskellwiki/Monomorphism_restriction)的原因。 – 2013-02-15 21:31:40
啊,謝謝。回想起來這很有道理(雖然我不確定爲什麼它不能專門化,因此需要記憶)。 – 2013-02-15 22:13:22
@JamesCunningham GHC識別[SPECIALIZED(http://www.haskell.org/ghc/docs/latest/html/users_guide/pragmas.html#specialize-pragma)編譯(雖然我沒有用它自己)。 – dave4420 2013-02-15 22:18:01