Наиболее распространенный способ использования базы данных на функциональном языке, если нет побочных эффектов? - PullRequest
8 голосов
/ 07 декабря 2011

Я пытаюсь осмыслить основную концепцию функциональных языков:

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

http://www.haskell.org/haskellwiki/Why_Haskell_matters#Functions_and_side-effects_in_functional_languages

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

Какой самый распространенный шаблон используется, чтобы обойти или обратиться к этому?

Ответы [ 3 ]

10 голосов
/ 07 декабря 2011

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

Подход Haskell, например, когдаРабота с побочными эффектами может быть объяснена довольно просто: пусть вся программа сама по себе является чистой (это означает, что функции всегда возвращают одни и те же значения для одних и тех же аргументов и не имеют побочных эффектов), но пусть возвращаемое значение main function - действие, которое можно запустить.

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

main:
  read contents of abc.txt into mystring
  write contents of mystring to def.txt

Вышеприведенная процедура main - это просто последовательность шагов, описывающая, как выполнить серию действий.

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

main = the reading of abc.txt into mystring followed by
       the writing of mystring to def.txt

Итак, main - это выражение, которое при оценке вернет действие, описывающее, что делать для выполнения программы.Фактическое выполнение этого действия происходит за пределами мира программистов.И это действительно, как это работает;ниже приведена фактическая программа на Haskell, которую можно скомпилировать и запустить:

main = readFile "abc.txt" >>= \ mystring ->
       writeFile "def.txt" mystring

a >>= b можно сказать как "действие a, за которым следует результат a, данный для действия b "в этой ситуации, и результатом работы оператора являются комбинированные действия a и b.Вышеприведенная программа, конечно, не является идиоматическим Haskell;можно переписать его следующим образом (удалив лишнюю переменную):

main = readFile "abc.txt" >>=
       writeFile "def.txt"

... или, используя синтаксический сахар и нотацию:

main = do
  mystring <- readFile "abc.txt"
  writeFile "def.txt" mystring

Все вышеперечисленные программыне только эквивалентны, но и идентичны в том, что касается компилятора.

Таким образом, файлы, системы баз данных и веб-серверы могут быть написаны как чисто функциональные программы: с помощью потоковЗначения действий через программу, так что они объединяются и, наконец, заканчиваются функцией main.Это дает программисту огромный контроль над программой, и поэтому чисто функциональные языки программирования так привлекательны в некоторых ситуациях.

5 голосов
/ 07 декабря 2011

Наиболее распространенный шаблон для работы с побочными эффектами и примесями в функциональных языках:

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

Примеры:

  • Лисп / Схема: set!
  • Clojure: ссылки и использование методов мутации для объектов Java
  • Scala: создание переменных с var
  • ML: не уверен в специфике, но Википедия говорит, что допускает некоторую нечистоту

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

Но решение Хаскелла, ИМХО, не самое распространенное.


(1) Не уверен в деталях здесь. Спасибо CAMcCann за указание на то, что эта метафора используется слишком часто и, возможно, не настолько точна.

4 голосов
/ 07 декабря 2011

Доступ к базе данных ничем не отличается от других случаев ввода-вывода, таких как print(17).

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

В Haskell решением проблемы ввода-вывода является использование монад. Например, если вы отметите HDBC , библиотеку базы данных haskell, вы увидите, что множество функций там возвращают действия ввода-вывода.

Некоторые языки, такие как Clean, используют типы уникальности, чтобы обеспечить такой же тип последовательности, который Haskell делает с монадами, но в настоящее время эти языки труднее найти.

...