Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
При всём при этом, у меня есть личные конкретные баттхёрты от quality of implementation в случае конкретного ghc — в сколь угодно нетривиальных параллельных программах GC начинает жрать непомерно много времени, потому что GC там хоть и параллельный, но не конкурентный, привет stop-the-world, если даже всего один HEC выжрал свой и соседние allocation area. Но это не свойство языка, впрочем. Либо, не отрицаю, я просто не умею писать многопоточные программы на хаскеле.
+RTS -A254m -qb0 -ki{size-of-l1-cache} зачастую очень сильно улучшает поведение (после 8.0 -qb0 не нужно, т.к. он выставляется динамически).Мой пост, мне хочется верить, тоже полезный, потому что дает возможность сформировать более взвешенное мнение о чисто функциональных языках и их ограничениях.
А так же о том, как осторожно надо относиться к хайпу по поводу какой бы то ни было технологии.
Тем не менее, если я правильно понимаю, правильное решето Эратосфена без priority queue в нем, скорее всего, до сих реализовать нельзя.Более-менее осмысленное императивное (а решето эратосфена это императивный алгоритм) решение можно было получить, когда появились массивы (array), библиотека от 2007 года, статью искать лень. С появлением пакетаvector2008 год, но не входит в стандарт, стало ещё проще. Учитывая, чтоSTуже было, то можно даже изолировать алгоритм и получить чистый результат какer n = V.toList $ runST $ do { x <- new 0; run x ; return $ unsafeFreeze x }.
При этом строчек будет столько же или меньше, вот некоторые будут выглядеть хуже, т.к. вместо привычного всемa[i] = 0будетunsafeWrite a i, в случае не возникающего в задачеa[i] = b[j]будет ещё хужеunsafeWrite a i =<< unsafeRead b j. Для меня учитывая количество получаемых плюсов этот синтаксис большой проблемой не является.
Почему там был использован prioity queue я не знаю, видимо кому-то хотелось получить алгоритм полностью в функциональном стиле, но я не знаю как это можно сделать эффективно без хорошей поддержи компилятора и более продвинутой системы типов, которой в ghc ещё нет. И главное я не знаю зачем нужно пиать полностью функциональную версию в чисто императивном алгоритме, если в языке есть прекрасная поддержка императивности и локализуемой изменяемости.
Лучше бы TimSort написали.
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Parallel (par, pseq)
import System.Random (randomRIO)
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
greater `par` lesser `par` lesser ++ x : greater
where lesser = quicksort [y | y <- xs, y <= x]
greater = quicksort [y | y <- xs, y > x]
main :: IO ()
main = do
(randoms :: [Int]) <- mapM (const $ randomRIO (1, 9)) $ take 50000 $ repeat 1
print $ quicksort randoms
Параллельная быстрая сортировка на Хаскеле и как нелегко её оказалось написать