Я пытался узнать, как работает STArray, но я не мог. (Док бедрен или, по крайней мере, тот, который я нашел).Как улучшить этот алгоритм с помощью 1) использовать массивы, 2) избежать конкатенации списков (ленивые списки?)?
В любом случае, у меня есть следующий алгоритм, но он использует много!, Что медленно. Как я могу преобразовать его в использование монады 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
Редактировать
К сожалению, !! это не проблема; в следующей версии алгоритма (ниже) я удалил использование !!; Кроме того, я установил 1 является простым, что это не так, как указано на @pedrorodrigues
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 ++ [Текущее]
STARray здесь не нужен, это просто пробный дебит алгоритма. Я думаю, что вы должны смотреть на стандартные функции манипулирования списком ('filter',' takeWhile', 'all',' any' и т. Д.), Так как проблема может быть оптимально и идиоматично решена с их использованием, и здесь вы «Сделав довольно обходные пути. –
Вам нужна быстрая реализация в функциональном стиле? затем см. предыдущий комментарий (и избегайте ошибочности слепого представления наборов списками). Или: вы хотите научиться использовать STArray, а затем точно описать, в чем проблема с STArray. Вы понимаете, что тогда вам нужно написать «императивный» код (все в монаде ST). – d8d0d65b3f7cf42
1, между прочим, не является простым. –