特定の数までのすべての素数を見つける関数を作成する次の 2 つの方法があるとします。
primes1 = iterate
(\ps -> ps ++ [([x |
x <- [last ps + 1..],
all (\p -> x `mod` p /= 0) ps] !! 0)])
[2]
primesTo1 :: Integer -> [Integer]
primesTo1 n = init $ head $ dropWhile (\p -> last p <= n) primes1
primes2 = iterate
(\ps -> ([x |
x <- [head ps + 1..],
all (\p -> x `mod` p /= 0) ps] !! 0)
: ps)
[2]
primesTo2 :: Integer -> [Integer]
primesTo2 n = tail $ head $ dropWhile (\p -> head p <= n) primes2
さまざまな関数が使用されているにもかかわらず、primesTo1
が よりもはるかに高速なのはなぜですか。で使用される, &の代わりに, &を使用します。primesTo2
primesTo1
++
last
init
:
head
tail
primesTo2
ghci
の出力:set +s
:
*Main> primesTo1 10000
...
(0.51 secs, 124779776 bytes)
*Main> primesTo2 10000
...
(3.30 secs, 570648032 bytes)
コンパイル済みghc -O2
:
$ time ./primes1
...
./primes1 0.06s user 0.00s system 68% cpu 0.089 total
$ time ./primes2
...
./primes2 0.28s user 0.00s system 98% cpu 0.283 total
注: Haskell に最適な素数ジェネレーターを探しているわけではありません。2 つの関数の速度の違いに混乱しているだけです。