“Ленивый IO” в Haskell?

Я пробую немного эксперимента в haskell, задаваясь вопросом, возможно ли использовать лень для обработки IO. Я хотел бы записать функцию, которая берет Строку (список Символов) и производит строку, лениво. Я хотел бы затем быть abily для ленивого питания, он изображает от IO, таким образом, каждый символ был бы обработан, как только это было доступно, и вывод будет произведен, поскольку необходимые символы стали доступными. Однако я не совсем уверен, могу ли я произвести ленивый список символов от входа в монаде IO.

8
задан Don Stewart 16 April 2011 в 19:21
поделиться

3 ответа

Я не знаю ответа на ваш вопрос, но использование 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 отпечатке.

14
ответ дан 5 December 2019 в 06:37
поделиться

Простейший метод выполнения ленивого ввода-вывода включает такие функции, как interact, readFile, hGetContents и подобные, как говорит dons; более подробное обсуждение этих функций есть в книге Real World Haskell, которая может быть вам полезна. Если мне не изменяет память, все подобные функции в конечном итоге реализуются с помощью unsafeInterleaveIO, о котором упоминает ephemient, так что при желании вы можете строить свои собственные функции таким образом.

С другой стороны, было бы разумно отметить, что unsafeInterleaveIO - это именно то, что написано на жести: unsafe IO. Его использование - или функций, основанных на нем - нарушает чистоту и ссылочную прозрачность. Это позволяет очевидно чистым функциям (то есть, не возвращающим IO) влиять на внешний мир при оценке, выдавать разные результаты при одних и тех же аргументах, и все прочие неприятные вещи. На практике большинство разумных способов использования unsafeInterleaveIO не вызовут проблем, а простые ошибки обычно приводят к очевидным и легко диагностируемым ошибкам, но вы теряете некоторые приятные гарантии.

Конечно, существуют альтернативы; на Hackage вы можете найти различные библиотеки, предоставляющие ограниченный, более безопасный lazy IO или концептуально иные подходы. Однако, учитывая, что в практическом использовании проблемы возникают крайне редко, я думаю, что большинство людей склонны придерживаться встроенных, технически небезопасных функций.

8
ответ дан 5 December 2019 в 06:37
поделиться
 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 , как в ответе Дона.)

3
ответ дан 5 December 2019 в 06:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: