如何制作自己的流媒体代码?我正在生成大约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运行它时,它首先开始冻结我的计算机,然后程序终止并且计算机恢复生命(然后谷歌浏览器拥有它所需要的资源,因为它耗尽了所有它资源。)
注意:我尝试过unsafeInterleaveIO,但它没有用。
完整代码位于:http://lpaste.net/109977
答案 0 :(得分:4)
replicateM
不会进行延迟流式传输。如果您需要从monadic操作传输结果,则应使用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
包。
作为一种快速而肮脏的解决方案,您可以使用惰性IO实现replicateM
的流式版本。
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
但我建议使用正确的流媒体库。
答案 1 :(得分:2)
等效的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)