Замена Clojure для ADT и сопоставления с образцом?

Всякий раз, когда в Haskell нам нужен какой-то вариант типа данных, мы будем использовать ADT в сочетании с сопоставлением с шаблоном. Что люди Clojure используют для таких случаев?

4 ответа

Ну, на самом деле есть несколько библиотек сопоставления с образцом, написанных для Clojure. Макросы Clojure делают подобные вещи возможными. Matchure является одним из самых последних. Есть еще кое-что для ADT в contrib.

Не обращая внимания на эти вещи, самое близкое, что у нас есть к ADT Haskell в ядре Clojure, - это новые записи и типы данных в Clojure 1.2. Но если вам не нужны преимущества, которые дает использование записи или типа данных, вы обычно просто используете карту. Clojure - это динамический язык, поэтому вы не получите статическую проверку типов, если в любом случае используете запись и тому подобное.

Clojure имеет "деструктуризацию", которая напоминает сопоставление с образцом, и часто используется в идиоматических Clojure. Смотрите это и это. Первый действительно ваш ответ здесь, на SO.;п

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

(defprotocol Fooable
  (foo [x]))

(defrecord AType [avalue]
  Fooable 
    (foo [x]
      (println (str "A value: " (:avalue x)))))

(defrecord BType [avalue]
  Fooable 
    (foo [x]
      (println (str "B value: " (:bvalue x)))))

(foo (AType. "AAAAAA"))    
=> A value: AAAAAA

(foo (BType. "BBBBBB"))    
=> B value: BBBBBB

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

Посмотрите на библиотеку matchure - она ​​должна быть включена в clojure-contrib в ближайшее время

Мне очень нравится yap как библиотека для сопоставления с образцом.

Наличие как ключевых слов, так и символов делает реализацию варианта достаточно простой в дополнение к библиотеке сопоставления с образцом.

Можно использовать мультиметоды и макросы.

Один из примеров можно найти ниже.

Итак, как они выглядят в Clojure?

Синтаксис, который будет использовать эта реализация ADT, будет выглядеть следующим образом:

(defadt Tree
 (Empty)
 (Leaf value)
 (Node left right))

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

(defmulti depth adt-type)
(defmethod depth Empty [_] 0)
(defmethod depth Leaf [_] 1)
(defmethod depth Node [node]
  (+ 1 (max (depth (node :left)) (depth (node :right)))))
(defmethod depth :default [_] 0)

Источник: http://gizmo385.github.io/clojure/programming/2015/08/11/adts-in-clojure.html

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