2010-10-03 4 views

ответ

18

Есть два метода, которые используются чисто функциональными языками программирования для моделирования побочных эффектов:

1) Тип мира, который представляет собой внешнее состояние, в котором каждое значение этого типа гарантируется системой типа, которые будет использоваться только один раз.

На языке, использующем этот подход, функции print и read могут иметь типы (string, world) -> world и world -> (string, world) соответственно.

Они могут быть использованы как это:

let main w = 
    let w1 = print ("What's your name?", w) in 
    let (str, w2) = read w1 in 
    let w3 = print ("Your name is "^name, w2) in 
    w3 

Но не так, как это:

let main w = 
    let w1 = print ("What's your name?", w) in 
    let (str, w2) = read w in 
    let w3 = print ("Your name is "^name, w2) in 
    w3 

(потому что вес используется дважды)

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

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

2) Монада IO, где все операции с побочными эффектами должны выполняться внутри этой монады.

При таком подходе все операции с побочными эффектами будут иметь тип io something. Например, print будет функцией с типом string -> io unit и read будет иметь тип io string.

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

Пример из выше будет выглядеть следующим образом с монадической IO:

let main = 
    (print "What's your name?") >>= 
    (lambda() -> read >>= 
    (lambda name -> print ("Your name is "^name))) 
+4

Ваш №2 является деталь реализации для вашего # 1. Мода IO просто автоматически переносит это мировое состояние для вас, упаковывая и распаковывая его по мере необходимости за любым синтаксисом, который использует ваша монада. –

+1

@JUST: Вы имеете в виду # 1 - деталь реализации №2, нет? Но тогда это не деталь реализации, если это интерфейс, который подвергается программисту. – sepp2k

+0

Да, правильно. Сожалею. # 1 - деталь реализации №2. –

1

Насколько я понимаю, если вы хотите иметь побочные эффекты на функциональном языке, вы должны их явно закодировать.

11

Есть несколько вариантов, доступных для выполнения операций ввода/вывода в функциональном языке.

  • Не будьте чисты. Многие функциональные языки не являются чисто функциональными. Более того, они поддерживают функциональное программирование, а не принуждают его выполнять. Это, безусловно, наиболее распространенное решение проблемы ввода-вывода в функциональном программировании. (Примеры: Lisp, Scheme, Standard ML, Erlang и т. Д.)
  • Преобразование потока. Ранний ввод-вывод Haskell был выполнен таким образом. Если у вас есть , уточните мою ссылку ниже. (Подсказка: вы, вероятно, этого не делаете.)
  • Продолжающий проход I/O («переходящий мир», упомянутый в других ответах). В этом случае вы передаете токен данных со своим вводом-выводом, который действует как необходимое «другое значение», чтобы сохранить ссылочную целостность живым. Это используется несколькими диалектами ML, если память служит.
  • «Продолжение» или «мировая» вещь выше может быть обернута в различные типы данных, большинство (в) известных - использование монадов в этой роли в Haskell. Обратите внимание, что это, как ни странно, то же самое при обложках, но утомление отслеживания переменных состояния «мир»/«продолжение» удаляется.

a research dissertation, который исчерпывающе анализирует их.

Функциональный ввод-вывод - это постоянная область исследований, и есть другие языки, которые затрагивают эту проблему интересными и умиротворяющими способами. Hoare logic предлагается использовать на некоторых языках исследований. Другие (например Mercury) использовать uniqueness typing. Третьи (например, Clean) используют effect systems. Из них у меня очень ограниченное воздействие только на Меркурий, поэтому я не могу комментировать подробности. Есть paper, который подробно изучает систему ввода-вывода Clean, однако, если вас интересует это направление.

Смежные вопросы