SoftCraft
разноликое программирование

Top.Mail.Ru

Почему никто не использует функциональные языки


Филип Вадлер

Перевод И.А. Дехтяренко

Было бы преувеличением сказать, что никто не использует функциональные языки. Телефонные вызовы в Европейском парламенте коммутируются программами, написанными на функциональном языке Erlang фирмы Ericsson. Виртуальные компакт-диски распределяются по сети Cornell через систему Ensemble, написанную на CAML, реальные компакт-диски распространяются в Европе компанией Polygram с использованием Natural Expert от Software AG. Функциональные языки выбраны для создания программ автоматического доказательства теорем, таких как система HOL, которая помогла отладить линию многопроцессорных систем HP9000. Эти приложения и другие описаны в предыдущей колонке [1].

Однако... Я работаю в Bell Labs, где были изобретены С и С++. В сравнении с пользователями С, "никто" - достаточно точная оценка числа пользователей функциональных языков. Сторонники функциональных языков заявляют, что они на порядок улучшают производительность. Эксперименты не всегда подтверждать, эту цифру - иногда они показывает улучшение только в четыре раза. Однако, не стоит пренебрегать кодом, который в четыре раза короче, в четыре раза быстрее писать, или в четыре раза проще поддерживать. Так почему же функциональные языки не используются более широко?

1 Причины

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

Большинство этих факторов остается серьезными препятствиями для многих систем. Заметные исключения - Ericsson Erlang и Harlequin ML Works, две системы промышленного уровня с обширной пользовательской средой и поддержкой.

Совместимость

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

Изоляционистский характер функциональных языков начинает уступать духу открытого обмена. Серьезные реализации теперь обычно обеспечивают интерфейсы к С, а иногда и к другим языкам. Взаимодействие с императивным миром достаточно просто для строгих языков подобных ML или Erlang, но сложно для ленивых языков, подобных Haskell или Clean, так как ленивость делает порядок вычислений трудно предсказуемым. Тем не менее, благодаря радующему взаимодействию теории и практики, недавние исследования показали, как абстрактные концепции типа монад или линейной логики могут применяться, для того чтобы плавно связать ленивые функциональные языки с реальным миром [2,3].

Преодоление изоляционизма - задача для всех, не только для функциональных программистов. Вычислительная промышленность начинает внедрять стандарты, такие как CORBA и COM, которые поддерживают создание программного обеспечения из компонентов многократного использования. Недавние работы позволяют упаковывать любую программу на Haskell как компонент COM, и вызывать любой компонент COM из Haskell. Помимо других применений, это позволяет при необходимости использовать его как язык сценариев для Microsoft Internet Explorer [4].

Библиотеки

Модная идея многократного использования программ существовала целую вечность в форме библиотек программ. Хорошая библиотека может создать или погубить язык. Tcl привлекает пользователей, прежде всего мощностью графической библиотеки Tk. Значительная часть привлекательности Java связана не собственно с языком, а скорее с библиотеками для графики, организации сети, баз данных, телефонии, и серверов предприятия. (Многое из непривлекательности Java обусловлено теми же самыми библиотеками).

Значительные усилия направлены на разработку библиотек графического интерфейса пользователя для функциональных языков. Haskell может похвастаться изобилием: Fudgets, Gadgets, Haggis и Hugs Tk. SML/NJ имеет две библиотеки: eXene и SML Tk. Язык SML имеет мощную систему модулей, которая упрощает создание гибких библиотек. Пример такой библиотеки - ML RISC [5], перенастраиваемый back-end, который использовался в компиляторах SML и С и был приспособлен для множества архитектур.

Мобильность

Я слышал о многочисленных проектах, где С выиграл у функциональных языков, не потому что С выполняется быстрее (хотя так часто бывает), но потому что гегемония С гарантирует, что он широко переносим. Например, исследователи из Lucent предпочли бы создавать язык баз данных PRL используя SML, но выбрали С++, потому что SML не был доступен на машине Amdahl, которую они должны были использовать. С другой стороны, абстрактные машины - популярная методика реализации и для функциональных языков и для Java, в частности, потому что создание машины на С облегчает её перенос на разнообразные архитектуры.

Доступность

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

Понятно, что большие проекты нежелательно доверять языку, не имеющему гарантированной продолжительной поддержки. Несколько функциональных языков доступно коммерчески: Research Software продает Miranda, Abstract Hardware продает Poly ML, ISL продает Poplog/SML, Harlequin продает ML Works, Ericsson имеет подразделение поддержки Erlang.

Тем не менее, для многих функциональных языков все ещё трудно обеспечить стабильного поставщика и надежную поддержку. Дополнительные трудности возникают из-за того, что функциональные языки часто активно развиваются, что создает противоречие между требованиями к стабильности и исследовательскими работами. Семейство Haskell пытается решать их, определив версию языка Standard Haskell, которая останется стабильной и поддерживаемой, в то время как другие версии Haskell продолжают развиваться [6].

Возможности упаковки Packagability

Следуя традиции Лиспа, многие реализации функциональных языков предлагают цикл read-eval-print. Несмотря на его удобство, необходимо обеспечить и некоторый способ преобразовать функциональную программу в самостоятельную прикладную программу. Большинство систем теперь позволяет это. Однако, эти системы часто внедряют полную библиотеку времени исполнения, и таким образом требуют неприемлемо большой памяти. Необходимо иметь возможность разрабатывать компактные автономные приложения.

Инструментальные средства

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

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

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

Обучение

Программисту, привыкшему к С, С++, или Java, функциональные программы кажутся странными. Требуется некоторое время, чтобы разобраться с записью f x y вместо f(x,y). И пряная (curried) пища и каррированые (curried) функции предполагают наличие вкуса.

Программисты, работающие на императивных языках, привыкают к определенному стилю программирования. Для данной задачи императивное решение может возникнуть немедленно, или его можно найти в легкодоступном справочнике, в то время как поиск соответствующего функционального решения может потребовать значительных усилий (даже если мы находим его более изящным). И хотя для большого круга проблем имеются эффективные решения на функциональных языках, остается несколько твердых орешков, для которых лучшие известные решения императивны по стилю. (По этим причинам, многие функциональные языки обеспечивают переход к императивному стилю, например SML включает изменяемые ссылки, как элементарный тип данных, а Haskell обеспечивает его через монады [7].)

Задача обучения не является трудноразрешимой. В Software AG нашли, что они могут обучать программистов использованию Natural Expert на однонедельном курсе, который включал ленивые вычисления, полиморфные типы и функции высшего порядка. Как правило, студенты раздражались, когда компилятор неоднократно отвергал программы из за ошибок типизации, но были приятно удивлены, когда их программы наконец проходили контроль типов и работали правильно с первой попытки [8].

Популярность

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

У управляющих свои заботы, у управляемых свои. Опыт работы с С++ или Java придаст приятный глянец вашему резюме, в то время как Haskell или SML принесут вам немного пользы. Система Pdiff фирмы Lucent, написанная на SML - ключевой инструмент поддержки программного обеспечения базы данных для коммутаторов 5ESS. Не удалось найти ни одного разработчика, который захотел бы взяться за поддержку системы, и, в конце концов, был нанят физик, пожелавший сменить область деятельности.

2 Не причины

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

Эффективность

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

Более важно то, что как показывает опыт, хотя эффективность помогает конкурировать с С, она вовсе не требуется для успеха. Tcl/Tk, Perl, и Visual Basic заняли видное положение с интерпретирующими реализациями. Java стал чрезвычайно популярным, имея эффективность гораздо ниже С. В функциональном мире Erlang достиг первых успехов как интерпретируемый язык.

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

"Они не понимают"

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

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

"Я пробовал изучать Haskell, и был впечатлен его элегантностью и тем, как он позволяет мне писать код, который работает с первой попытки (или со второй). Однако, я не исследователь. Я занимаюсь коммерческой разработкой программного обеспечения и мне требуется документация и стабильность". [9]

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

3 Уроки

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

Убийственные применения

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

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

В предыдущей колонке [1] перечислены некоторые из таких применений, и подчеркнуто как используется мощность функциональных языков. Разработчиков сетей связи привлекает Erlang своей поддержкой параллелизма и распределенных вычислений; последнее непосредственно связано с тем фактом, что функциональные данные, являющиеся неизменным, хорошо пригодны для передачи по сети. Создателей систем доказательств теорем привлекает ML с его поддержкой символьных вычислений. Генетики тяготеют к CPL/Kleisli, потому что его система типов поддерживает доступ к гетерогенным базам данных, и потому что математические свойства функциональных языков могут использоваться для оптимизации запросов. Разработчики экспертных систем привлечены к Natural Expert, потому что ленивые вычисления походят на рассуждения обратным логическим выводом, и потому что ленивые вычисления дают возможность создавать экономичный интерфейс к базам данных.

Первоклассные исследования в функциональном программировании часто связаны с применениям. Университет Карнеги-Меллона собирает свои работы по функциональному программированию в проекте Fox, где предпринята попытка написать сетевые драйверы на SML. Исследователи из Чалмерского университета тесно связаны с Carlstedt и Logikkonsult и, помимо прочего, применили частичные вычисления к планированию авиаперевозок. Глазго и Йорк объединились, чтобы выпустить целую книгу о применениях. Орегонский институт совместно с Intel рассматривают разработку аппаратуры. Исследователи из Йельского университета применили функциональное программирование к исполнению музыки и пониманию естественного языка, и вместе с Microsoft работают над анимацией. Однако, большинство этих исследований не сконцентрировало вокруг прикладных библиотек или пакетов, которые могли бы привлекать существенные сообщества пользователей.

Приложения хранят неизведанные глубины. Прыгайте, вода прекрасна!

Акценты исследований

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

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

В рамках функционального программирования, главное направление - анализ программ и разработка компиляторов. Лидеры области должны двигаться к новым участкам инструментальных средств и приложений, а конференции и журналы должны явно приветствовать вклады в этих областях. Гопал Гупта организует Первую международную конференцию по практическим аспектам декларативных языков PADL99 [10].

Чтобы помочь смене парадигмы, область может установить новые критерии для оценки новых работ. Саймон Джонс и я только что закончили редакционную статью для Journal of Functional Programming, которая приветствует работы по практике и опыту функционального программирования, и излагает критерии, которые мы применяем для их оценки [11].

Скромное предложение

Даже скромная реализация функционального языка должна обеспечивать межъязыковые интерфейсы, отладчик, и профилировщик. Исходя из этого критерия, мне известны только несколько скромных реализацияй функциональных языков, такие как Ericsson Erlang, Harlequin's ML Works, и INRIA CAML. Эндрю Толмач и Эндрю Аппель изобрели оригинальный отладчик для реализация SML/NJ [12], но пока реализация развивалась, отладчик не поддерживался, и для текущего выпуска SML/NJ не доступного никакого отладчика.

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

Надежда

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

Ссылки
[1] Philip Wadler, An angry halfdozen, ACM SIGPLAN Notices 33(2):25-30, February 1998.
[2] Philip Wadler. How to declare an imperative. ACM Computing Surveys, 29(3):240-263, September 1997.
[3] Rinus Plasmeijer and Marko van Eekelen, Pure and efficient functional programming using the "unique" features of Clean. ACM SIGPLAN Notices, to appear.
[4] Simon Peyton Jones, Erik Meijer, and Daan Leijen. Scripting COM components in Haskell. IEEE Fifth International Conference on Software Reuse, Vancouver, BC, June 1998. www.haskell.org/active/activehaskell.html
[5] Lal George, MLRISC: Customizable and Reusable Code Generators, Bell Labs technical report, May 1997. www.cs.bell-labs.com/cm/cs/what/smlnj/doc/MLRISC/
[6] John Hughes, editor, Standard Haskell. www.cs.chalmers.se/~rjmh/Haskell/
[7] J. Launchbury and S. L. Peyton Jones, Lazy functional state threads. In ACM Conference on Programming Language Design and Implementation, Orlando, Florida, 1994.
[8] Nigel W. O. Hutchison, Ute Neuhaus, Manfred Schmidt-Schauss, and Cordy Hall. Natural Expert: a commercial functional programming environment. Journal of Functional Programming, 7(2):163-182, March 1997.
[9] S. Alexander Jacobson alex@i2x.com, letter to Haskell mailing list, 3 May 1998.
[10] Gopal Gupta, chair, First International Conference on Practical Aspects. www.cs.nsmsu.edu/~complog/conferences/padl99/
[11] Simon Peyton Jones and Philip Wadler. Editorial: Practice and experience papers, Journal of Functional Programming, to appear. www.dcs.glasgow.ac.uk/jfp/
[12] Andrew Tolmach and Andrew Appel, A Debugger for Standard ML. Journal of Functional Programming, 5(2):155-200, April 1995.

Philip Wadler, Why no one uses functional languages, ACM SIGPLAN Notices, August 1998 (.ps)