Это вопрос о библиотеке Haskell streaming
.
Stream (Of a) m r
- это «поток отдельных значений Haskell, полученных из действий в некоторой монаде m
и возвращающих значение типа r
».Streaming.Prelude
определяет множество полезных функций, которые позволяют создавать хорошие потоковые приложения:
import qualified Streaming.Prelude as S
S.print $ do
S.yield "a"
S.yield "b"
S.yield "c"
Учебное пособие хорошо для начала.
Теперь конкретная проблема под рукойкак использовать этот фреймворк с монадой, требующей тщательной реализации и освобождения ресурсов.Пакет streaming-with
кажется подходящим кандидатом, он имеет функцию
bracket :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
, которая получает (m a
), освобождает (a->m c
) и использует (* 1025)*) ресурс.Все три действия заключены в возвращенном m b
.withFile
является хорошим примером того, как использовать это:
withFile :: FilePath -> IOMode -> (Handle -> m r) -> m r
withFile fp md = bracket (liftIO (openFile fp md)) (liftIO . hClose)
Получение и выпуск ручки приятно совмещают использование Handle->m r
.
Но: я абсолютно не вижукак это следует использовать с Stream (Of a) m r
.Я должен предоставить a->m b
, и я получу m b
.Как это должно быть связано, чтобы я получил Stream
?
Чтобы понять это, давайте поиграем с withFile
:
import System.IO
use :: Handle -> IO (S.Stream (Of String) IO ())
use = return . S.repeatM . hGetLine
main :: IO ()
main = do
str <- S.withFile "input.dat" ReadMode use
S.print str
, но в результате получим hGetLine: illegal operation (handle is closed)
,Это действительно имеет смысл, к тому времени, когда S.print str
называется withFile
, уже получил и отпустил ручку.Итак, давайте переместим потребление потока внутри функции use
:
use :: Handle -> IO ()
use h = do
S.print $ S.repeatM (hGetLine h)
, и это даст hGetLine: invalid argument (invalid byte sequence)
.Я не совсем уверен, что означает эта ошибка.isEOFError
будет приемлемым, но «недопустимая последовательность байтов»?В любом случае, это тоже не работает.
У меня заканчиваются идеи ... Как это сделать?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- просто игрушечный пример, вопрос в том, как правильно создать и использовать поток внутри
bracket
. *1059*