Каковы альтернативы монад использовать IO в чисто функциональном программировании? - PullRequest
34 голосов
/ 29 января 2010

монады описаны как решение haskell для работы с IO. Мне было интересно, есть ли другие способы борьбы с IO на чистом функциональном языке.

Ответы [ 6 ]

35 голосов
/ 29 января 2010

Какие существуют альтернативы монадам для ввода / вывода на чистом функциональном языке?

Мне известны две альтернативы в литературе:

  • Это так называемая система линейных типов . Идея состоит в том, что значение линейного типа должно использоваться точно один раз: вы не можете игнорировать его и не можете использовать его дважды. Помня об этой идее, вы задаете состояние мира абстрактному типу (например, World) и делаете его линейным. Если я отмечу линейные типы звездочкой, то вот типы некоторых операций ввода / вывода:

    getChar :: World* -> (Char, World*)
    putChar :: Char -> World* -> World*
    

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

    Уникальность набора текста на языке Чистота основана на линейности.

    Эта система имеет пару преимуществ; в частности, он не навязывает общий порядок событий, которые делают монады. Это также имеет тенденцию избегать «IO sin bin», которое вы видите в Haskell, где все эффективные вычисления брошены в монаду IO, и все они полностью упорядочены, хотите ли вы общий порядок или нет.

  • Другая система, о которой я знаю, предшествовала монадам и Чистоте и основана на идее, что интерактивная программа - это функция от (возможно бесконечной) последовательности запросов к (возможно) бесконечный) последовательность ответов . Эта система, которую называли «диалогами», была просто адом для программирования. Никто не пропускает это, и это не было ничего особенно рекомендовать это. Его ошибки хорошо перечислены в статье, в которой вводились монадические операции ввода-вывода ( императивное функциональное программирование ) Уодлера и Пейтона Джонса. В этой статье также упоминается система ввода / вывода, основанная на продолжениях, которая была введена группой Yale Haskell, но которая была недолгой.

8 голосов
/ 07 февраля 2010

Помимо линейных типов, есть также система эффектов .

5 голосов
/ 29 января 2010

Императивное функциональное программирование Пейтона Джонса и Вадлера необходимо прочитать, если вас интересует функциональный ввод-вывод. Другие подходы, которые они обсуждают:

  • Диалоги, которые являются ленивыми потоками ответов и запросов

type Dialogue = [Response] -> [Request]

main :: Dialogue

  • Продолжения - каждая операция ввода-вывода принимает продолжение в качестве аргумента

  • Линейные типы - система типов ограничивает вас таким образом, что вы не можете копировать или уничтожать внешнее состояние, что означает, что вы не можете дважды вызывать функцию с одним и тем же состоянием.

5 голосов
/ 29 января 2010

Если под «чистым» вы подразумеваете «ссылочно-прозрачный», то есть то, что прикладная функция свободно взаимозаменяема с ее оцененным результатом (и, следовательно, что вызов функции с одинаковыми аргументами каждый раз имеет один и тот же результат), любая концепция IO с состоянием в значительной степени исключен по определению.

Есть две грубые стратегии, о которых я знаю:

  • Пусть функция выполняет IO, но убедитесь, что она никогда не будет вызвана дважды с одинаковыми аргументами; это обходит проблему, позволяя функциям быть тривиально «ссылочно прозрачными».

  • Рассматривать всю программу как единственную чистую функцию, принимающую «весь полученный вход» в качестве аргумента и возвращающую «весь полученный результат», причем оба представлены в виде ленивого потока для обеспечения интерактивности.

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

В Haskell IO - это тип монады, который автоматически пропускает последовательное состояние через код (аналогично функционально чистой монаде State), так что, концептуально, каждый вызов нечистой функции получает различное значение неявного "состояния внешнего мира".

Другой популярный подход, о котором я знаю, использует что-то вроде линейных типов для аналогичной цели; гарантируя, что нечистые функции никогда не получат одинаковые аргументы дважды, имея значения, которые не могут быть скопированы или дублированы, так что старые значения «состояния внешнего мира» не могут быть сохранены и использованы повторно.

4 голосов
/ 29 января 2010

Уникальная типизация используется в Чисто

3 голосов
/ 29 мая 2014

Функциональное реактивное программирование - еще один способ справиться с этим.

...