unsafeInterleaveIO
や遅延IOを使用しないでください。これは正確には、反復子が予測できないリソース管理をもたらす遅延IOを回避するために作成された問題です。トリックはになり、リストは決して作成されず、イテレートを使用してストリームされます。これを実証するために、私自身のライブラリpipes
の例を使用します。
まず、定義:それを実行してみましょう、
今
prompt100 :: Producer Int IO()
prompt100 = replicateM_ 1000 $ do
lift $ putStrLn "Enter an integer: "
n <- lift readLn
yield n
:
>>> runPipe $ printer <+< take' 1 <+< prompt100
Enter an integer:
3<Enter>
3
import Control.Monad
import Control.Monad.Trans
import Control.Pipe
-- Demand only 'n' elements
take' :: (Monad m) => Int -> Pipe a a m()
take' n = replicateM_ n $ do
a <- await
yield a
-- Print all incoming elements
printer :: (Show a) => Consumer a IO r
printer = forever $ do
a <- await
lift $ print a
を今度は、私たちのユーザーに意味し、彼らは私たちにとって本当に大きなリストを作成要求されてみましょう
我々は唯一の整数を要求するので、それは唯一、1つの整数をユーザーに要求します!
あなたはgetLargeList
からの出力でprompt100
を交換したい場合は、あなただけの書き込み:
yourProducer :: Producer b IO()
yourProducer = do
xs <- lift getLargeList
mapM_ yield xs
を...そして実行します:
>>> runPipe $ printer <+< take' 1 <+< yourProducer
これを遅延リストをストリーミングし、構築することはありませんメモリ内にリストしてください。すべて安全ではありません。IO
ハックです。必要な要素の数を変更するには、渡す値を変更するだけです。take'
pipes
tutorialをControl.Pipe.Tutorial
と読んでください。
あなたがhereを見つけることができ、対象のオレグのオリジナルのスライドを読んで、怠惰なIOは、問題が発生する理由についての詳細を学ぶために。彼は遅延IOを使って問題を説明する素晴らしい仕事をしています。あなたが遅延IOを使用するように強いられると感じるたびに、本当に必要なものはiterateeライブラリです。
おそらくこれが役立ちます。 http://stackoverflow.com/questions/3270255/is-haskells-mapm-not-lazy –
Anton、私はこのトピックを読んだが、私は答えを見つけられなかった:怠惰な計算のためのmapMの代替があるかどうか。 –
@DmitryBespalov同じ型の署名ではありません。 'Monad'は、後でそれを延期するための抽象概念を持っていません。それが' mapM'がレイジーになるためにはあなたがしなければならないことです。 – Carl