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



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



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

532   6  

6 ответов:

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

есть несколько предостережений, которые должны быть сделаны об этой статье. Наиболее важным является то, что он не обращается к ленивым функциональным языкам, таким как Haskell. птица, Джонс и Де Мур [1997] продемонстрировать, что проблема создается Pippenger можно решить на ленивом функциональном языке в O (n) время, но они не устанавливают (и, насколько я знаю, никто не имеет), Может ли ленивый функциональный язык решить все проблемы в том же асимптотическом времени выполнения, что и язык с мутацией.

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

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

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

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

ссылки

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

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

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

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

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

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

EDIT:

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

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

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

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

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

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

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

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

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

функции как первый класс Типы

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

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

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

монады

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

Ленивая Оценка И Рекурсия

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

S-Выражений

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

Comments

    Ничего не найдено.