3

我正在尝试从由 WriterT 包装的 IO 生成无限的惰性值流。我正在使用管道来使用此流并将其写入文件。我很清楚 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

看到没有人给出完整的答案,我将我的评论转换为一个。最大的优点之一conduit是它使我们免于使用惰性 IO!使用复杂WriterT与这个想法背道而驰。相反,我们应该制作generator一个Source,然后用一个文件插入它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 回答