Haskell аналог обратного цитирования и сплайсинга lisp - PullRequest
4 голосов
/ 20 апреля 2019

В некоторых списках (например, elisp , common lisp ) есть функция, называемая обратным цитированием.

Позволяет построить список при оценке или объединении в него некоторых элементов. Например:

 `(1 2 (3 (+ 4 5))) 
  ⇒ (1 2 (3 (+ 4 5)))  ; just quoted unevaluated list

 `(1 2 (3 ,(+ 4 5)))
  ⇒ (1 2 (3 9))     ; (+ 4 5) has been evaluated

 `(1 2 ,@(list 3 (+ 4 5)))
  ⇒ (1 2 3 9)       ; (3 9) has been spliced into the list

Полагаю, в Haskell некоторая часть обратных ссылок может выглядеть так:

 [backquote| 1, 2, @$(replicate 2 3), 2 + 2 |]
 ⇒ [1, 2, 3, 3, 4]

Интересно, возможно ли встраивание в список, подобный этому, и был ли он реализован.

1 Ответ

3 голосов
/ 25 апреля 2019

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

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

Вы провели параллель между списками Lisp и списками Haskell, но в Lisp S-выражение (т. Е. "Пары с атомами", особенно с атомарными символами) - это гибкая и вездесущая структура данных, используемая не только для представления Лисп-код, но также и как переходное представление, это как минимум первое соображение для любых сложных структурированных данных. Таким образом, большинство программ на Лиспе тратят много времени на генерацию и управление этими структурами, поэтому «литералы» S-выражений часто встречаются в коде на Лиспе. И S-выражение «почти литералы», где необходимо вычислить несколько подвыражений, более удобно писать с использованием механизма обратных кавычек, чем пытаться создать выражение с меньшими литералами и вычисляемыми фрагментами, используя такие функции, как cons, list, append и т. Д.

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

Ну, так же, как Lisp с его S-выражениями, программы на Haskell тратят много времени на генерацию и манипулирование ADT, а Haskell также имеет удобный синтаксис для литералов ADT и «почти литералов». Они объединены в единый синтаксис «приложения функции» с литеральными и вычисляемыми частями, дифференцированными с помощью использования конструкторов (идентификаторы с начальной заглавной буквой или инфиксные операторы, начинающиеся с двоеточия) по сравнению с неконструкторами (идентификаторы с начальной строчной буквой или инфиксом). операторы без начального двоеточия). Конечно, для некоторых конструкторов (списков и кортежей) существует некоторый дополнительный синтаксис.

Например, сравните следующие выражения в кавычках в Lisp и Haskell:

;; Lisp
(setq baz `(node ,id
                 (node ,(+ id 1) ,left-tree leaf)
                 (node ,(+ id 2) leaf ,right-tree)))
-- Haskell
baz = Node id (Node (id + 1) left_tree Leaf) (Node (id + 2) Leaf right_tree)

В Haskell-версии этого «почти литерала» конструкторы Node и Leaf представляют цитируемые части; инфиксные выражения left-tree, right-tree и + представляют вычисленные части, и они синтаксически различимы по обычным правилам для конструкторов и неконструкторов.

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

...