Я пытаюсь провести небольшой эксперимент в Хаскелле, задаваясь вопросом, можно ли использовать лень для обработки ввода-вывода. Я хотел бы написать функцию, которая берет строку (список Chars) и создает строку, лениво. Я хотел бы тогда быть умело лениво подавать персонажи из IO, поэтому каждый персонаж будет обработан, как только он будет доступен, и выход будет создан, поскольку необходимые символы станут доступными. Тем не менее, я не совсем уверен, что/как я могу создать ленивый список символов из ввода внутри IO-монады."Lazy IO" в Haskell?
ответ
Регулярная строка IO в Haskell является ленивой. Поэтому ваш пример должен просто работать из коробки.
Вот пример, используя «будут взаимодействовать» функцию, которая применяет функцию к ленивому потока символов:
interact :: (String -> String) -> IO()
Давайте отфильтровывать букву «е» из входного потока, лениво (т.е. пробег в постоянном пространстве):
main = interact $ filter (/= 'e')
Вы также можете использовать getContents и putStr, если хотите. Они все ленивы.
Запуск его для фильтрации букву «е» из словаря:
$ ghc -O2 --make A.hs
$ ./A +RTS -s < /usr/share/dict/words
...
2 MB total memory in use (0 MB lost due to fragmentation)
...
поэтому мы видим, что он бежал в постоянном 2M след.
Вы также можете увидеть этот эффект в командной строке. Запустите программу Don 'A' в оболочке/терминале/независимо от используемой ОС и введите текст прямо в нее. Предполагая, что это строка буферизована, когда вы нажимаете клавишу ввода после каждой строки, вы сразу увидите отфильтрованный текст, даже если программа, похоже, делает только один «вызов» для фильтрации. – Nefrubyr
unsafeInterleaveIO :: IO a -> IO a
unsafeInterleaveIO
аллосIO
вычисления, чтобы отложить лениво. Когда передано значение типаIO a
,IO
будет выполняться только в том случае, если требуется значениеa
. Это используется для чтения ленивых файлов, см.System.IO.hGetContents
.
0 Например: main = getContents >>= return . map Data.Char.toUpper >>= putStr
лень; когда вы загружаете символы в stdin, вы получите символы на stdout.
(Это то же самое, как написание main = interact $ map Data.Char.toUpper
, как в ответ Донс гг.)
Самый простой способ сделать ленивый IO включает в себя такие функции, как interact
, readFile
, hGetContents
и таким, как донов говорит; есть более подробное обсуждение этих вопросов в книге Real World Haskell, которые могут оказаться полезными. Если память обслуживает меня, все такие функции в конечном итоге реализуются с использованием unsafeInterleaveIO
, что ephemient упоминает, поэтому вы можете также создавать свои собственные функции таким образом, если хотите.
С другой стороны, было бы разумно отметить, что unsafeInterleaveIO
- это именно то, что он говорит на олове: небезопасный IO. Используя его - или функции на его основе - breaks purity and referential transparency. Это позволяет, по-видимому, чистые функции (т. Е. Не возвращать действие IO
), чтобы влиять на внешний мир при оценке, давать разные результаты по тем же аргументам и всем этим неприятным вещам. На практике наиболее разумные способы использования unsafeInterleaveIO
не вызовут проблем, и простые ошибки обычно приводят к очевидным и легко диагностированным ошибкам, но вы потеряли некоторые хорошие гарантии.
Есть альтернативы, конечно; вы можете найти различные библиотеки в Hackage, которые предоставляют ограниченные, safer lazy IO или conceptually different approaches. Однако, учитывая, что проблемы возникают редко в практическом использовании, я думаю, что большинство людей склонны придерживаться встроенных, технически небезопасных функций.
- 1. Принудительная оценка lazy IO
- 2. Отображение IO в Haskell
- 3. IO проблемы в Haskell
- 4. Haskell: TCO и Lazy оценка
- 5. Lazy IO in haskell: Как вернуть ленивый список, который генерируется некоторыми заблокированными IO?
- 6. Haskell Recursive IO
- 7. Haskell IO порядок выполнения
- 8. Haskell IO - ручка закрыт
- 9. обработки Haskell [IO String]
- 10. Haskell: [String] to IO()
- 11. Haskell IO пример
- 12. другой haskell IO issue
- 13. haskell io stream memory
- 14. Haskell Сравнение IO UTCTime
- 15. Haskell IO russian symbols
- 16. Haskell. Обработка исключений IO
- 17. Haskell IO Рекурсия
- 18. haskell network io hgetline
- 19. Haskell IO с цифрами
- 20. Haskell ReplicateM IO
- 21. Haskell параллелизм поведение IO
- 22. Haskell Safe IO
- 23. Haskell Некорректное IO выходной
- 24. Базовый Haskell IO (IO String -> Int)?
- 25. Не может IO в Haskell
- 26. Memoizing IO вычислениям в Haskell
- 27. Resizable массив IO в Haskell
- 28. Строки трубопроводов haskell в IO
- 29. Haskell Console IO в блокноте ++
- 30. Haskell монада: IO [Double] к [IO Double]
Просьба пояснить: вы хотите использовать функцию, которая принимает строку и «производит» строку --- «производит» = «возвращает», «выходы в дескриптор файла» или что? И тогда вы хотите «лениво накормить персонажей из IO» - что это значит? – dave4420