Haskell, Lisp и многословие

Для тех из вас, кого вы испытали как в Haskell, так и в каком-то вкусе Lisp, мне любопытно, как "приятно" (использовать ужасный термин), это написать код в Haskell vs. Lisp.

Некоторая предыстория: сейчас я изучаю Haskell, ранее работая с Scheme и CL (и немного набегая на Clojure). Традиционно вы можете считать меня фанатом динамических языков для лаконичности и быстроты, которые они обеспечивают. Я быстро влюбился в макросы Lisp, так как это дало мне еще один способ избежать подробностей и шаблонов.

Я нахожу Haskell невероятно интересным, так как он вводит меня в способы кодирования, которых я не знал. У него определенно есть некоторые аспекты, которые кажутся похожими на то, что они помогут в достижении маневренности, как легкость написания частичных функций. Тем не менее, я немного обеспокоен тем, что теряю макросы Lisp (я предполагаю, что я их потеряю, правда, мне сказали, что я еще не узнал о них?) И статической системы набора текста.

Будет ли кто-нибудь, кто сделал приличное количество кодирования в обоих мирах, комментируя, как эти события отличаются, которые вы предпочитаете, и если указанное предпочтение является ситуационным?

Ответ 1

Короткий ответ:

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

[Примечание: существует Template Haskell", который позволяет писать макросы так же, как в Lisp, но, строго говоря, вы никогда не должны это нужно.]

Ответ 2

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

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

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

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

Ответ 3

Там меньше потребности в метапрограммировании в Haskell, чем в Common Lisp, потому что многое может быть структурировано вокруг монад, а добавленный синтаксис делает встроенные DSL менее похожими на дерево, но всегда есть Template Haskell, как упоминалось ShreevatsaR и даже Liskell (синтаксис Haskell semantics + Lisp), если вам нужны скобки.

Ответ 4

Что касается макросов, вот страница, в которой говорится об этом: Привет Хаскелл, До свидания Lisp. Это объясняет точку зрения, где макросы просто не нужны в Haskell. Он содержит короткий пример для сравнения.

Пример, когда требуется макрос LISP, чтобы избежать оценки обоих аргументов:

(defmacro doif (x y) `(if ,x ,y))

Пример случая, когда Haskell не систематически оценивает оба аргумента, без необходимости чего-то вроде определения макроса:

doif x y = if x then (Just y) else Nothing

И voilà

Ответ 5

Я обычный программист Lisp.

Попробовав Haskell некоторое время назад, моя личная нижняя строка заключалась в том, чтобы придерживаться CL.

Причины:

  • динамическая типизация (проверьте Динамическое и статическое типирование - анализ на основе шаблонов Паскаль Костанца)
  • необязательные аргументы и ключевые слова
  • унифицированный гомозиконный синтаксис списка с макросами
  • префиксный синтаксис (нет необходимости запоминать правила приоритета)
  • нечистый и, следовательно, более подходящий для быстрого прототипирования
  • мощная объектная система с метаобъектным протоколом
  • зрелый стандарт
  • широкий диапазон компиляторов

У Haskell есть свои достоинства, конечно, и он делает некоторые вещи принципиально другим способом, но он просто не сокращает его в долгосрочной перспективе для меня.

Ответ 6

В Haskell вы можете определить функцию if, что невозможно в LISP. Это возможно из-за лени, которая позволяет больше модульности в программах. Эта классическая статья: Почему FP имеет значение Джона Хьюза, объясняет, как лень повышает композиционную способность.

Ответ 7

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

Ответ 8

Есть действительно классные вещи, которые вы можете достичь в Lisp с макросами, которые громоздки (если это возможно) в Haskell. Возьмем, к примеру, макрос "memoize" (см. Главу 9 Петра Норвига PAIP). С его помощью вы можете определить функцию, скажем, foo, а затем просто оценить (memoize 'foo), которая заменяет глобальное определение foo на memoized версию. Можете ли вы добиться такого же эффекта в Haskell с функциями более высокого порядка?