STArray がどのように機能するかを学ぼうとしましたが、できませんでした。(Docは貧弱です、または少なくとも私が見つけたものです)。
いずれにせよ、次のアルゴリズムがありますが、多くの !! を使用しており、遅いです。STArrayモナドを使用するように変換するにはどうすればよいですか?
-- The Algorithm prints the primes present in [1 .. n]
main :: IO ()
main = print $ primesUpTo 100
type Nat = Int
primesUpTo :: Nat -> [Nat]
primesUpTo n = primesUpToAux n 2 [1]
primesUpToAux :: Nat -> Nat -> [Nat] -> [Nat]
primesUpToAux n current primes =
if current > n
then primes
else primesUpToAux n (current + 1) newAcum
where newAcum = case isPrime current primes of
True -> primes++[current]
False -> primes
isPrime :: Nat -> [Nat] -> Bool
isPrime 1 _ = True
isPrime 2 _ = True
isPrime x neededPrimes = isPrimeAux x neededPrimes 1
isPrimeAux x neededPrimes currentPrimeIndex =
if sqrtOfX < currentPrime
then True
else if mod x currentPrime == 0
then False
else isPrimeAux x neededPrimes (currentPrimeIndex + 1)
where
sqrtOfX = sqrtNat x
currentPrime = neededPrimes !! currentPrimeIndex
sqrtNat :: Nat -> Nat
sqrtNat = floor . sqrt . fromIntegral
編集
おっと、!! 問題ではありませんでした。アルゴリズムの次のバージョン (以下) では、!!; の使用を削除しました。また、@pedrorodriguesが指摘したように、1が素数ではないことを修正しました
main :: IO ()
main = print $ primesUpTo 20000
type Nat = Int
primesUpTo :: Nat -> [Nat]
primesUpTo n = primesUpToAux n 1 []
primesUpToAux :: Nat -> Nat -> [Nat] -> [Nat]
primesUpToAux n current primesAcum =
if current > n
then primesAcum
else primesUpToAux n (current + 1) newPrimesAcum
where newPrimesAcum = case isPrime current primesAcum of
True -> primesAcum++[current]
False -> primesAcum
isPrime :: Nat -> [Nat] -> Bool
isPrime 1 _ = False
isPrime 2 _ = True
isPrime x neededPrimes =
if sqrtOfX < currentPrime
then True
else if mod x currentPrime == 0
then False
else isPrime x restOfPrimes
where
sqrtOfX = sqrtNat x
currentPrime:restOfPrimes = neededPrimes
sqrtNat :: Nat -> Nat
sqrtNat = floor . sqrt . fromIntegral
今、この質問は実際には約2つの質問です:
1.- リストの代わりに配列を使用するようにこのアルゴリズムを変換する方法は? (Haskellで状態と配列を処理する方法を学ぶためのものです)コメントで誰かがすでに答えていますが、あまりよく説明されていない例を指しています。
2.- 新しい素数が見つかるたびにリストの連結をなくすには?
True -> primesAcum++[現在]