IO monad中的惰性计算

时间:2013-06-30 10:46:53

标签: haskell monads monad-transformers

我正在尝试从WriterT包装的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)

1 个答案:

答案 0 :(得分: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")