Как мне обрабатывать бесконечный список объектов ввода-вывода в Haskell?

Я пишу программу, которая читает из списка файлов. Каждый файл либо содержит ссылку на следующий файл, либо отмечает, что это конец цепочки.

Поскольку я новичок в Haskell, мне показалось, что идиоматический способ справиться с этим - это ленивый список возможных файлов для этой цели, у меня есть

getFirstFile :: String -> DataFile
getNextFile :: Maybe DataFile -> Maybe DataFile

loadFiles :: String -> [Maybe DataFile]
loadFiles = iterate getNextFile . Just . getFirstFile

getFiles :: String -> [DataFile]
getFiles = map fromJust . takeWhile isJust . loadFiles

Пока все хорошо. Единственная проблема заключается в том, что, поскольку getFirstFile и getNextFile должны открывать файлы, мне нужно, чтобы их результаты были в монаде ввода-вывода. Это дает модифицированную форму

getFirstFile :: String -> IO DataFile
getNextFile :: Maybe DataFile -> IO (Maybe DataFile)

loadFiles :: String -> [IO Maybe DataFile]
loadFiles = iterate (getNextFile =<<) . Just . getFirstFile

getFiles :: String -> IO [DataFile]
getFiles = liftM (map fromJust . takeWhile isJust) . sequence . loadFiles

. Проблема в том, что, поскольку итерация возвращает бесконечный список, последовательность становится бесконечным циклом. Я не знаю, что делать дальше. Есть ли более ленивая форма последовательности, которая не затронет все элементы списка? Должен ли я перенастроить карту и takeWhile, чтобы работать внутри монады ввода-вывода для каждого элемента списка? Или мне нужно отбросить весь процесс бесконечного списка и написать рекурсивную функцию для завершения списка вручную?

8
задан Thomas Eding 11 October 2011 в 12:57
поделиться