2010-01-28 7 views

ответ

33

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

Я знаю двух альтернатив в литературе:

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

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

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

    Уникальность печатания на языке Clean основана на линейности.

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

  • Другая система Я знаю еще до монады и чистый и основан на идее о том, что интерактивная программе является функцией от (возможно, бесконечных) последовательностей запросов к (возможно, бесконечные) последовательностей ответы. Эта система, которая называлась «диалоги», была чистым адом для программирования. Никто не скучает по нему, и в этом нет ничего, чтобы рекомендовать его. Его недостатки хорошо перечислены в the paper that introduced monadic I/O (Imperative Functional Programming) Вадлером и Пейтоном Джонсом. В этой статье также упоминается система ввода-вывода, основанная на продолжениях, которые были введены группой Yale Haskell, но которая была недолговечной.

+1

Секвенирование через привязку к монаде в значительной степени просто проверяет тип продолжения-прохода в любом случае, не так ли? Мое впечатление заключалось в том, что монады и продолжения в основном взаимозаменяемы, за исключением того, что продолжения явно не являются, вообще говоря, теплыми * или * нечеткими. –

+2

Продолжения образуют монаду, но монады явно * не * продолжения. CPS намного эффективнее, потому что вам разрешено делать копии вещей (включая продолжение!). Монады ограничивают вещи намного жестче, чем просто проверка типов. –

+0

«Монады решительно не являются продолжениями» - нет, но отношения - это не только экземпляр InstanceOf. Ср http://lambda-the-ultimate.org/node/3235 Lawvere Theories and Monads, Hyland & Power, 2007. –

4

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

5

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

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

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

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

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

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

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

5

Imperative Functional Programming от Peyton Jones и Wadler - это необходимо прочитать, если вы заинтересованы в функциональном IO. Другие подходы, которые они обсуждают, являются:

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

type Dialogue = [Response] -> [Request]

main :: Dialogue

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

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

3

Functional Reactive Programming - это еще один способ справиться с этим.

+1

Я никогда не слышал термин «Функциональное реактивное программирование». Можете ли вы изменить его на «Функциональное реактивное программирование»? Отличный ответ. –

+0

Нет проблем, спасибо, что заметили. Не знаю, как я ошибся. –