Я пробую немного эксперимента в haskell, задаваясь вопросом, возможно ли использовать лень для обработки IO. Я хотел бы записать функцию, которая берет Строку (список Символов) и производит строку, лениво. Я хотел бы затем быть abily для ленивого питания, он изображает от IO, таким образом, каждый символ был бы обработан, как только это было доступно, и вывод будет произведен, поскольку необходимые символы стали доступными. Однако я не совсем уверен, могу ли я произвести ленивый список символов от входа в монаде IO.
Я не знаю ответа на ваш вопрос, но использование Reflector звучит разумно для меня.
Мне интересно, зачем вы это делаете? Может быть, имеет смысл использовать Composite образцов для агрегирования поведения, а затем пытаться объединить командные привязки?
-121--3409502- Нет никаких трюков, единственное, что я могу придумать в отношении обнаружения, если stdout перенаправляется в другое место, это сделать это, как в простой функции C, как показано здесь перенаправлено
, кроме того, что бремя лежит на вас, чтобы обеспечить безопасность сообщений... использует procfs trickery требует корневых привилегий для доступа к определенным функциям procfs... поэтому убедитесь, что вы положили туда чек, чтобы убедиться, что он не запущен как root...
int isredirected(void){
if (!isatty(fileno(stdin))) return 1;
return 0;
}
Надеюсь, что это поможет, С наилучшими пожеланиями, Том.
-121--5044333-Регулярная последовательность ввода-вывода в Haskell ленива. Так что ваш пример должен просто работать из коробки.
Вот пример, используя функцию «interact», которая применяет функцию к ленивому потоку символов:
interact :: (String -> String) -> IO ()
Давайте отфильтруем букву «e» из входного потока, лениво (т.е. запустить в постоянном пространстве):
main = interact $ filter (/= 'e')
Вы также можете использовать getContents и putStr, если хотите. Они все ленивы.
Запуск его для фильтрации буквы «e» из словаря:
$ 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 отпечатке.
Простейший метод выполнения ленивого ввода-вывода включает такие функции, как interact
, readFile
, hGetContents
и подобные, как говорит dons; более подробное обсуждение этих функций есть в книге Real World Haskell, которая может быть вам полезна. Если мне не изменяет память, все подобные функции в конечном итоге реализуются с помощью unsafeInterleaveIO
, о котором упоминает ephemient, так что при желании вы можете строить свои собственные функции таким образом.
С другой стороны, было бы разумно отметить, что unsafeInterleaveIO
- это именно то, что написано на жести: unsafe IO. Его использование - или функций, основанных на нем - нарушает чистоту и ссылочную прозрачность. Это позволяет очевидно чистым функциям (то есть, не возвращающим IO
) влиять на внешний мир при оценке, выдавать разные результаты при одних и тех же аргументах, и все прочие неприятные вещи. На практике большинство разумных способов использования unsafeInterleaveIO
не вызовут проблем, а простые ошибки обычно приводят к очевидным и легко диагностируемым ошибкам, но вы теряете некоторые приятные гарантии.
Конечно, существуют альтернативы; на Hackage вы можете найти различные библиотеки, предоставляющие ограниченный, более безопасный lazy IO или концептуально иные подходы. Однако, учитывая, что в практическом использовании проблемы возникают крайне редко, я думаю, что большинство людей склонны придерживаться встроенных, технически небезопасных функций.
unsafeInterleaveIO :: IO a -> IO a
unsafeInterleaveIO
позволяет отложить отложенное вычислениеIO
. При передаче значения типаIO a
,IO
будет выполняться только тогда, когда требуется значениеa
. Это используется для реализации отложенного чтения файлов, см.System.IO.hGetContents
.
Например, main = getContents >> = return. map Data.Char.toUpper >> = putStr
ленивый; когда вы вводите символы на стандартный ввод, вы будете получать символы на стандартный вывод.
(Это то же самое, что и запись main = interact $ map Data.Char.toUpper
, как в ответе Дона.)