我有一个使用我自己的monadProducer
创建依赖于随机性的值:Random
policies :: Producer (Policy s a) Random x
Random
mwc-random
是一个可以从ST
or运行的包装器IO
:
newtype Random a =
Random (forall m. PrimMonad m => Gen (PrimState m) -> m a)
runIO :: Random a -> IO a
runIO (Random r) = MWC.withSystemRandom (r @ IO)
生产者通过policies
简单的强化学习算法产生越来越好的策略。
我可以通过索引到 5,000,000 次迭代后有效地绘制策略policies
:
Just convergedPolicy <- Random.runIO $ Pipes.index 5000000 policies
plotPolicy convergedPolicy "policy.svg"
我现在想在每 500,000 步上绘制中间策略,看看它们是如何收敛的。我写了几个函数,它们获取生产者policies
并提取一个列表([Policy s a]
然而,这些函数花费的时间(10 倍)和使用更多的内存(4 倍)比仅仅绘制上面的最终策略,即使学习迭代的总数应该是相同的(即 5,000,000)。我怀疑这是由于提取了一个禁止垃圾收集器的列表,这似乎是管道的一种惯用用法:
惯用的管道样式在生成元素时立即使用它们,而不是将所有元素加载到内存中。
当Producer
超过一些随机单子(即Random
)并且我想要产生的效果时,使用这样的管道的正确方法是IO
什么?
换句话说,我想将 aProducer (Policy s a) Random x
插入到Consumer (Policy s a) IO x
.