我有一個Producer
創建依賴於隨機性的值,用我自己的Random
單子:我如何通過IO操作在一些非IO monad中慣用和高效地使用管道?
policies :: Producer (Policy s a) Random x
Random
超過mwc-random
的包裝,可以從ST
或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
生產者通過簡單的強化學習算法產生更好更好的策略。
我可以有效地繪製後的政策,比方說,500萬次迭代通過索引進入policies
:
Just convergedPolicy <- Random.runIO $ Pipes.index 5000000 policies
plotPolicy convergedPolicy "policy.svg"
我現在要繪製每50萬步中間政策,看看他們是如何收斂。我寫了幾個函數,生成policies
製作者,並提取一個列表([Policy s a]
),比如10個策略 - 每500,000次迭代一次 - 然後繪製所有這些策略。但是,即使學習迭代的總數應該相同(即5,000,000),這些函數花費的時間(10x)和使用更多內存(4x)的時間也要比繪製上述最終策略要多。我懷疑這是由於抽取名單抑制垃圾收集器,這似乎是一個unidiomatic使用管道的:因爲它們產生的,而不是加載的所有元素到內存
慣用管道風格立即消耗的元素。
什麼是正確的做法,以消耗管這樣當Producer
是在一些隨機的單子(即Random
)和IO
我想產生的效果是什麼?
換句話說,我想插入一個Producer (Policy s a) Random x
到Consumer (Policy s a) IO x
。
'Random'是否有'MonadIO'實例?如果是這樣的話,你將會有'hoist liftIO :: Consumer(Policy s a)IO x - > Consumer(Policy s a)Random x'。還有其他的方法可以解決這個問題,有些可能會更快,但它可能有助於更多地瞭解「Random」。 – Michael
@邁克爾:它不,我不希望它。它只能做隨機性和*不*通用IO。理想情況下,我很喜歡這個解決方案,它只依賴於'Random'具有'runIO :: Random a - > IO a'功能的事實。 –
我想你不希望由於生成隨機性的方式而使'hoist runIO'將'Producer(Policy s a)Random x'轉換爲'Producer(Policy s a)IO x'。 – Michael