3

WriterT によってラップされた IO から値の無限の遅延ストリームを生成しようとしています。コンジットを使用してこのストリームを消費し、ファイルに書き込みます。bind オペレーターでの IO の厳密さはよく知っていますが、そこに IO を持つこのストリームを遅延して生成するにはどうすればよいでしょうか?

無理ならレイジーSTに変えてみようかな。

import Data.Conduit
import Control.Monad.Writer
import Data.DList as DL

type Stream = WriterT (DL.DList String) IO ()

generator :: Stream
generator = do
    tell $ DL.singleton "something"
    generator

runStream :: Stream -> IO ()
runStream s = runResourceT $ stream s
    where stream s       = sourceStream s $$ sinkStream -- sinkStream just writes to a file
          sourceStream s = do w <- liftIO $ execWriterT s
                           CL.sourceList (DL.toList w)
4

1 に答える 1

1

誰も完全な回答をしていないので、コメントを 1 つに変換します。の最大の利点の 1 つは、conduit遅延 IO を使用する必要がないことです。複雑なものを使用するWriterTと、アイデアに反します。代わりに、 を作成generatorSource、それを file でプラグインする必要がありますSink:

import Control.Monad
import Data.Conduit
import Data.Conduit.Binary
import qualified Data.ByteString.Char8 as BS

generator :: Monad m => Source m String
generator = replicateM_ 3 (yield "something\n")
    -- or `forever (...)` if you want an infinite loop

-- Reads Strings, converts them to ByteStrings and writes
-- to a file.
sinkStream :: MonadResource m => FilePath -> Sink String m ()
sinkStream file = mapInput BS.pack (const Nothing) (sinkFile file)

main :: IO ()
main = runResourceT (generator $$ sinkStream "/tmp/output.txt")
于 2013-07-04T05:11:23.330 に答える