Эффективность чисто функционального программирования

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

Уточнение из комментария itowlson : есть ли какая-либо проблема, для которой самый известный неразрушающий алгоритм асимптотически хуже самого известного деструктивного алгоритма, и если да, то насколько?

Согласно Pippenger [1996] , при сравнении системы Lisp, которая является чисто функциональной (и имеет строгую оценочную семантику, а не ленивую) к той, которая может мутировать данные, алгоритм, написанный для нечистого Lisp, который работает в O ( n ), может быть переведен к алгоритму в чистом Lisp, который работает в O ( n log n ) времени (основанный на работе Бен-Амрама и Галиля [1992] об имитации памяти произвольного доступа с использованием только указателей). Pippenger также устанавливает, что существуют алгоритмы, для которых это лучшее, что вы можете сделать; существуют проблемы, которые представляют собой O ( n ) в нечистой системе, которые являются Ω ( n log n ) в чистой системе.

В этой статье есть несколько предостережений. Самое главное, что он не касается ленивых функциональных языков, таких как Haskell. Bird, Jones and De Moor [1997] демонстрируют, что проблема, созданная Pippenger, может быть решена на ленивом функциональном языке в O ( n ) времени, но они не устанавливают (и, насколько я знаю, никто не имеет), или не ленивый функциональный язык может решить все проблемы в том же асимптотическом времени, что и язык с мутацией.

Задача, построенная Пиппэндэром, требует, чтобы Ω ( n log n ) была специально построена для достижения этого результата и не обязательно представляла практические, реальные проблемы. Есть несколько ограничений на проблему, которые немного неожиданны, но необходимы для доказательства работы; в частности, проблема требует, чтобы результаты вычислялись в режиме онлайн, не имея возможности получить доступ к будущему входу, и что вход состоит из последовательности атомов из неограниченного набора возможных атомов, а не набора фиксированного размера. И статья только устанавливает (нижнюю границу) результаты для нечистого алгоритма линейного времени работы; для задач, требующих большего времени работы, возможно, что дополнительный коэффициент O (log n ), замеченный в линейной задаче, может быть «поглощен» в процессе дополнительных операций, необходимых для алгоритмов с большим временем работы. Эти разъяснения и открытые вопросы кратко рассматриваются Бен-Амрамом [1996] .

На практике многие алгоритмы могут быть реализованы на чистом функциональном языке с той же эффективностью, что и на языке с изменяемыми структурами данных. Для хорошей ссылки на методы, используемые для эффективного использования функциональных структур данных, см . «Чистофункциональные структуры данных» Криса Окасаки [Okasaki 1998] (который является расширенной версией его диссертации [Okasaki 1996] ).

Любой, кто должен реализовать алгоритмы на чисто функциональных структурах данных, должен прочитать Окасаки. Вы всегда можете получить в худшем случае замедление O (log n ) на операцию, моделируя изменчивую память со сбалансированным двоичным деревом, но во многих случаях вы можете сделать значительно лучше, чем это, и Окасаки описывает много полезных методов: от амортизированных методов до реальных, которые постепенно амортизируют работу. Чисто функциональные структуры данных могут быть немного трудными для работы и анализа, но они обеспечивают множество преимуществ, таких как ссылочная прозрачность, которые полезны в оптимизации компилятора, параллельных и распределенных вычислениях и в реализации таких функций, как управление версиями, отмена и откат.

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

Рекомендации

  • Бен-Амрам, Амир и Галил, Цви 1992. «О указателях против адресов». Журнал ACM, 39 (3), стр. 617-648, июль 1992 г.
  • Бен-Амрам, Амир 1996 года. «Заметки о сравнении Пиппенгера чистого и нечистого Лиспа» Неопубликованная рукопись, DIKU, Университет Копенгагена, Дания
  • Bird, Richard, Jones, Geraint и De Moor, Oege 1997. «Больше поспешности, меньше скорости: ленивая и нетерпеливая оценка» Журнал функционального программирования 7, 5 с. 541-547, сентябрь 1997 г.
  • Окасаки, Крис 1996. «Чисто функциональные структуры данных» Кандидатская диссертация, Университет Карнеги-Меллона
  • Окасаки, Крис 1998. «Чисто функциональные структуры данных» Cambridge University Press, Cambridge, UK
  • Пиппенгер, Николас 1996. « Симпозиум ACM по принципам языков программирования», стр. 104-109, январь 1996 г.

Действительно, существует несколько алгоритмов и структур данных, для которых не известно асимптотически эффективное чисто функциональное решение (ti, одно реализуемое в чистом lambda-исчислении), даже с лени.

  • Вышеупомянутый союз-находка
  • Хэш-таблицы
  • Массивы
  • Некоторые алгоритмы графа

Однако мы предполагаем, что на «императивных» языках доступ к памяти – O (1), тогда как в теории, которая не может быть так асимптотически (т. Е. Для неограниченных размеров проблем) и доступа к памяти в огромном наборе данных, всегда O (log n) , которые могут быть эмулированы на функциональном языке.

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

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

Тот факт, что другие ответы утверждают, что никогда не может быть никакой разницы, и что, например, единственный «недостаток» чисто функционального кода состоит в том, что он может быть распараллелен, дает вам представление об информированности / объективности сообщества функционального программирования по этим вопросам ,

РЕДАКТИРОВАТЬ:

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

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

Если строгая функция имеет сложность O (f (n)) в строгом языке, то она также имеет сложность O (f (n)) на ленивом языке. Зачем беспокоиться? 🙂

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

Эскиз доказательства. Учитывая фиксированную верхнюю границу использования памяти, нужно иметь возможность написать виртуальную машину, которая выполняет набор императивных инструкций с той же асимптотической сложностью, как если бы вы фактически выполнялись на этой машине. Это связано с тем, что вы можете управлять изменчивой памятью как постоянной структурой данных, предоставляя O (log (n)) чтение и запись, но с фиксированной верхней границей использования памяти вы можете иметь фиксированный объем памяти, распад до O (1). Таким образом, функциональная реализация может быть императивной версией, выполняемой в функциональной реализации виртуальной машины, и поэтому они должны иметь одинаковую асимптотическую сложность.

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

«Функциональный» – это набор различных функций, каждый из которых независимо полезен, и его более полезно рассматривать каждый отдельно.

неизменность

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

Функции как типы первого classа

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

Возможность создания функций (например, преrotation Action в просто действие также весьма полезна в некоторых сценариях.

Здесь также следует отметить синтаксис lambda, потому что вы получаете только синтаксис lambda, когда рекламируете функции для типов первого classа. Синтаксис lambda может быть очень выразительным и кратким.

Монады

Это тонкая, но очень мощная конструкция. Он так же эффективен, как ключевое слово yield, используемое для создания classов IEnumerable в C #. По сути, он создает для вас машину состояний под обложками, но ваша логика выглядит линейной.

Ленивая оценка и recursion

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

S-выражение

Я думаю, я не уверен, где это сделать, но способность обрабатывать не скомпилированный код как объект (и проверять / модифицировать его), например, Lisp S-Expressions или LINQ Expressions, в некотором роде, самый мощный инструмент функционального программирования. Большинство новых «беглых» интерфейсов .NET и DSL используют комбинацию синтаксиса lambda и LINQ Expressions для создания некоторых очень сжатых API. Не говоря уже о Linq2Sql / Linq2Nhibernate, где ваш код C # «магически» выполняется как SQL, а не как код C #.

Interesting Posts

Как отправить значения ввода формы и вызвать метод в компоненте JSF

Бесплатное программное обеспечение для преобразования видео, которое поддерживает широкоэкранный формат

Как защитить свой API, который был создан с использованием Google Cloud Endpoints?

Переместить каждые 7 столбцов в новую строку в Excel

Получить значения из файла свойств с помощью Groovy

Как вы используете данные модуля Fortran 90

JAR Bundler с использованием OSXAdapter, заставляющий приложение запаздывать или заканчиваться

Подсекции всегда смежные 1s?

Можно ли удалить ребенка из коллекции и решить проблемы в SaveChanges?

Удаление неиспользуемых расширений Firefox

загрузка файла PDF

Указывает ли объявление, использующее «авто», выражение extern, использующее спецификатор конкретного типа?

Ошибка приложения при запуске из-за java.lang.IllegalArgumentException: column ‘_id’ не существует

Как полностью отключить выключение или перезапуск Windows в XP

Обновление до сервисов Google Play: 9.0.0 Ошибка Не удалось решить: com.google.android.gms: play-services-measurement: 9.0.0

Давайте будем гением компьютера.