Haskell аналог обратного цитирования и сплайсинга lisp

В некоторых списках (например, 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 ответ

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

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

Вы провели параллель между списками Lisp и списками Haskell, но в Lisp S-выражение (то есть "пары с атомами", особенно с атомарными символами) - это гибкая и вездесущая структура данных, используемая не только для представления кода на Lisp, но также и как переходное представление, это как минимум первое соображение для любых сложных структурированных данных. Таким образом, большинство программ на Лиспе тратят много времени на генерацию и управление этими структурами, поэтому "литералы" 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 предоставляет более классический вид синтаксиса обратных цитат.

Другие вопросы по тегам