Являются ли некоторые структуры данных более подходящими для функционального программирования, чем другие? - PullRequest
19 голосов
/ 01 марта 2009

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

Это имеет смысл, поскольку гораздо проще повторно использовать часть (неизменяемого) списка или дерева при создании нового, чем делать это с массивом.

Итак, мои вопросы:

  • Существуют ли действительно существенно разные модели использования структур данных между функциональным и императивным программированием?
  • Если это так, это проблема?
  • Что если вам действительно нужна хеш-таблица для какого-либо приложения? Вы просто проглатываете дополнительные расходы, понесенные за модификации?

Ответы [ 9 ]

14 голосов
/ 01 марта 2009

Книга Чисто функциональные структуры данных подробно описывает ваши вопросы и включает в себя большое сочетание теории и реализаций, прежде всего в ML - приложение также содержит реализации на Haskell, поэтому вы сможете следовать вместе с немного дополнительной переворачивания страницы. Это очень хорошее (хотя и сложное по частям) чтение, если вы действительно заинтересованы в подробном ответе на ваши вопросы. Сказав это, я думаю, что ephemient дал превосходный короткий ответ.

редактировать: Стивен Хьюиг предоставил ссылку на тезис, с которого начиналась книга. Хотя я не прочитал его, единственное, чего не хватает (судя по оглавлению), это реализации на Haskell.

12 голосов
/ 16 мая 2009

Говоря как кто-то, кто занимался ОО в течение многих лет, а недавно строил крупный проект, требующий большой скорости (автоматизированная система торговли опционами в реальном времени) в Haskell:

  • Существуют ли действительно существенно разные модели использования структур данных между функциональным и императивным программированием?

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

  • Если это так, это проблема?

Это был не один для меня, за исключением того, что мне пришлось потратить некоторое время на изучение нового способа работы. В частности, производительность, безусловно, не была проблемой: система, над которой я работаю, работает значительно быстрее, чем предыдущая реализация Java, например.

  • Что если вам действительно нужна хеш-таблица для какого-либо приложения? Вы просто проглатываете дополнительные расходы, понесенные за модификации?

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

11 голосов
/ 01 марта 2009
  • Да. Обычно кортежи, списки и частично оцененные функции являются очень распространенными структурами данных в функциональных языках программирования. Изменяемые структуры данных, такие как массивы и (реальные) хеш-таблицы, используются гораздо реже, потому что они не вписываются в Haskell. SML (который также функционален, но не ленив) может использовать массивы более естественно, чем Haskell, но списки все еще более распространены, поскольку они хорошо отображаются в рекурсивных алгоритмах.
  • Я не уверен, как на это ответить. Проблема для кого?
  • Существуют реализации ассоциативных массивов (эквивалент «хэш-таблицы»), которые могут продолжать совместно использовать большую часть своей базовой структуры даже после различных обновлений. Я считаю, что GHC's Data.Map делает; также, Edison имеет довольно много ленивых / функционально дружественных структур данных.
4 голосов
/ 03 марта 2009

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

Как уже упоминалось выше, книга Криса Окасаки о чисто функциональных структурах данных очень хороша.

4 голосов
/ 01 марта 2009

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

Поскольку действительно требуется хеш-таблица, учтите, что поиск O (lg n) всего в двадцать раз медленнее поиска O (1) при поиске миллиона элементов.

1 голос
/ 01 марта 2009
  • Существуют ли действительно существенно разные модели использования данных? структуры между функциональными и императивное программирование?

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

  • Если это так, это проблема?

Проблема заключается в императивных парадигмах, которые не смогут сохранить эффективность, поскольку распараллеливание становится все более необходимым - единственным выходом для этих языков будет избавление от побочных эффектов, но тогда они станут сломанными функциональными языками - но тогда зачем мне их беспокоить, когда есть несколько довольно хороших, функциональных языков. Кроме того, семантику функциональных языков легче контролировать, следовательно, функциональные программы могут быть доказаны правильными, тогда как их аналоги в C ++ не могут (пока, во всяком случае). Следовательно, многие формальные средства проверки основаны на функциональных языках - например, ACL2 основан на общем lisp, а Cryptol - на Haskell. Поскольку формальная проверка является волной будущих функциональных языков, они могут лучше интегрироваться в эти инструменты. Короче говоря, до свидания C, C ++ и тому подобное - хороший опыт! Кто-то давно должен был взять им 30 или 6.

  • Что если вам действительно нужна хеш-таблица для какого-то приложения? Вы просто проглотить лишние расходы понесены за модификации?

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

1 голос
/ 01 марта 2009

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

Возможно, вы захотите пересмотреть, если вы смотрите на дополнительные расходы на алгоритм. Почему хеш-таблица (для нерекурсивного алгоритма O (1)) требует дополнительных затрат? Какое преимущество вы получаете от его использования по сравнению с деревом или списком?

0 голосов
/ 20 августа 2014

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

0 голосов
/ 01 марта 2009

Да, основным отличием является неизменность данных, которые могут включать в себя код (см. Функции более высокого порядка). См. Страницу Wikipedia на Purely Functional для списка общих типов данных и их использования. Будет ли это проблемой или нет, зависит от того, как вы на это смотрите. Программирование на функциональном языке имеет много преимуществ, если оно соответствует типу задачи, над которой вы работаете. Хеш-таблица - это тип ассоциативного массива, но он не тот, который вы хотите использовать в функциональном языке, из-за перефразирования, которое вам придется делать при вставке, и низкой производительности без массивов. Вместо этого попробуйте реализацию 100. * Haskell в Data.Map для ассоциативного массива.

...