Clojure 替代 Haskell 的 ADT 和模式匹配?

问题描述 投票:0回答:5

每当在 Haskell 中我们需要一些变体数据类型时,我们都会将 ADTs 与模式匹配结合使用。 Clojure 人们在此类用例中使用什么?

haskell functional-programming clojure pattern-matching algebraic-data-types
5个回答
10
投票

实际上有一些为 Clojure 编写的模式匹配库。 Clojure 的宏使这种事情成为可能。 Matchure 是最新的之一。 contrib 中甚至还有一些用于 ADT 的东西。

不管这些东西,我们在核心 Clojure 中与 Haskell 的 ADT 最接近的是 Clojure 1.2 中的新记录和数据类型。但是,除非您需要使用记录或数据类型带来的好处,否则通常只使用映射。 Clojure 是一种动态语言,因此如果您使用记录等,您将不会获得静态类型检查。

Clojure 具有“解构”功能,这让人想起模式匹配,并且在惯用的 Clojure 中被大量使用。请参阅

这个这个。前者是您真正在这里的答案。 ;p


4
投票
这在一定程度上取决于您想要做什么。但假设需要基于数据类型的多态行为的常见情况,协议通常是一个好方法:

(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 的可能值以及协议函数的多态行为。



0
投票
我非常喜欢 yap 作为模式匹配库。

同时拥有关键字和符号的事实使得在模式匹配库之上实现变体变得非常容易。


0
投票
可以使用多种方法和宏。

下面是一个示例。

那么它们在 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

© www.soinside.com 2019 - 2024. All rights reserved.