Что означает "чистый" в "чистом функциональном языке"?

Haskell был назван "чисто функциональным языком".

Что означает "чистый" в этом контексте? Какие последствия это имеет для программиста?

7 ответов

Решение

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

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

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

"Чистый" и "функциональный" - два разных понятия, хотя одно не очень полезно без другого.

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

Функциональный язык программирования - это язык, в котором функции являются первоклассными. Другими словами, вы можете манипулировать функциями с той же легкостью, с которой вы можете манипулировать всеми другими первоклассными значениями. Например, возможность использовать "функцию, возвращающую bool" в качестве "структуры данных, представляющей набор" будет легко в функциональном языке программирования.

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

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

Чистая функция - это функция, которая не имеет побочных эффектов - она ​​принимает значение и возвращает значение. Нет глобального состояния, которое бы изменяло функции. Чистый функциональный язык - это язык, который заставляет функции быть чистыми. Чистота имеет ряд интересных последствий, таких как тот факт, что оценка может быть ленивой - поскольку вызов функции не имеет цели, кроме как вернуть значение, тогда вам не нужно фактически выполнять функцию, если вы не собираетесь использовать его ценность. Благодаря этому такие вещи, как рекурсивные функции в бесконечных списках, распространены в Haskell.

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

Строго говоря, чисто функциональный язык - это функциональный язык (т. Е. Язык, где функции являются первоклассными значениями), где выражения не имеют побочных эффектов. Термин "чисто функциональный язык" является синонимом.

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

Есть полезный расслабленный смысл, в котором языки, такие как Haskell и Erlang, можно считать чисто функциональными, а языки, такие как ML и Scheme, нельзя. Язык может считаться чисто функциональным, если существует достаточно большое, полезное и хорошо охарактеризованное подмножество, где побочные эффекты невозможны. Например, в Haskell все программы, тип которых не построен из IO или другая монада, обозначающая эффект, не имеет побочных эффектов. В Erlang все программы, которые не используют библиотеки ввода-вывода или функции параллелизма, не имеют побочных эффектов (это более сложная задача, чем в случае с Haskell). И наоборот, в ML или Scheme, побочный эффект может быть скрыт в любой функции.

С этой точки зрения, чисто функциональное подмножество Haskell можно рассматривать как встроенный язык для работы с поведением внутри каждой монады (конечно, это странная перспектива, поскольку почти все вычисления происходят в этом "встроенном" подмножестве), и чисто функциональное подмножество Erlang можно рассматривать как встроенный язык, имеющий дело с локальным поведением.


У Грэма Хаттона немного другой и довольно интересный взгляд на тему чисто функциональных языков:

Иногда термин "чисто функциональный" также используется в более широком смысле для обозначения языков, которые могут включать вычислительные эффекты, но без изменения понятия "функция" (о чем свидетельствует тот факт, что основные свойства функций сохраняются.) Обычно вычисление выражения может привести к "задаче", которая затем выполняется отдельно, чтобы вызвать вычислительные эффекты. Этапы оценки и выполнения разделены таким образом, что этап оценки не ставит под угрозу стандартные свойства выражений и функций. Например, механизмы ввода / вывода Haskell являются такими.

Т.е. в Haskell функция имеет тип a -> b и не может иметь побочных эффектов. Выражение типа IO (a -> b) может иметь побочные эффекты, но это не функция. Таким образом, в Haskell функции должны быть чистыми, следовательно, Haskell является чисто функциональным.

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

Я потерял счет, сколько раз у меня возникали проблемы с неочевидными побочными эффектами при расширении / исправлении (или попытке исправить) кода.

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

Что такое побочный эффект?

Я видел побочные эффекты, объясняемые как

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

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

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

Амр Сабри написал статью о том, что такое чистый функциональный язык. Haskell по этому определению считается чистым, если мы игнорируем такие вещи, как unsafePerformIO. Использование этого определения также делает ML и Erlang нечистыми. Есть подмножества большинства языков, которые квалифицируются как чистые, но лично я не думаю, что очень полезно говорить о том, что C является чистым языком.

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

Другие вопросы по тегам