2013-06-30 3 views
3

Я пытаюсь создать бесконечный ленивый поток значений из IO, завернутый WriterT. Я использую каналы, чтобы потреблять этот поток и записывать его в файл. Я хорошо знаю строгость IO в своем операторе привязки, так как я могу создать этот поток лениво, имея там IO?ленивое вычисление внутри IO monad

Если это невозможно, следует ли попытаться перейти на ленивый 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

Да, почему бы просто не использовать ленивый IO? –

+2

Почему вы просто не переписываете свой генератор как «Source IO String»? –

+0

@DonStewart Я просто хочу возиться с каналами, чтобы увидеть, насколько хорошо подходит IO :-) – Ricardo

ответ

1

Увидев, что никто не дал полного ответа, я конвертирую свой комментарий в один. Одним из самых больших преимуществ conduit является то, что это избавляет нас от использования ленивого ввода-вывода! Использование сложного WriterT идет вразрез с идеей. Вместо этого мы должны сделать generatorSource, а затем просто подключить его с файлом 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") 
Смежные вопросы