Как мне получить ленивый поток в складку?
Как создать собственный потоковый код? Я генерировал около 1 000 000 000 случайных пар военных колод и хотел, чтобы они лениво текли в складки, но я получил космическую утечку! Вот соответствующий раздел кода:
main = do
games <- replicateM 1000000000 $ deal <$> sDeck --Would be a trillion, but Int only goes so high
let res = experiment Ace games --experiment is a foldl'
print res --res is tiny
Когда я запускаю его с -O2, он сначала начинает зависать на моем компьютере, а затем программа умирает, и компьютер возвращается к жизни (а затем Google Chrome располагает ресурсами, которые ему нужны, чтобы кричать на меня за использование всех своих ресурсов.)
Примечание: я попытался unsafeInterleaveIO, и это не сработало.
Полный код по адресу: http://lpaste.net/109977
2 ответа
replicateM
не делает ленивого потокового Если вам нужно передать результаты от монадических действий, вы должны использовать библиотеку, такую как conduit
или же pipes
,
Ваш пример кода может быть написан для поддержки потоковой передачи с такими каналами:
import Data.Conduit
import qualified Data.Conduit.Combinators as C
main = do
let games = C.replicateM 1000000 $ deal <$> sDeck
res <- games $$ C.foldl step Ace
-- where step is the function you want to fold with
print res
Data.Conduit.Combinators
модуль из conduit-combinators
пакет.
В качестве быстрого и грязного решения вы могли бы реализовать потоковую версию replicateM
используя ленивый IO.
import System.IO.Unsafe
lazyReplicateIO :: Integer -> IO a -> IO [a] --Using Integer so I can make a trillion copies
lazyReplicateIO 0 _ = return []
lazyReplicateIO n act = do
a <- act
rest <- unsafeInterleaveIO $ lazyReplicateIO (n-1) act
return $ a : rest
Но я рекомендую использовать правильную потоковую библиотеку.
Эквивалент pipes
Решение:
import Pipes
import qualified Pipes.Prelude as Pipes
-- Assuming the following types
action :: IO A
acc :: S
step :: S -> A -> S
done :: S -> B
main = do
b <- Pipes.fold step acc done (Pipes.replicateM 1000000 action)
print (b :: B)