Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure's substitute for Haskell's ADTs and pattern matching?

Whenever in Haskell we need some variant data type, we would use ADTs in conjunction with pattern matching. What do Clojure folks use for such use cases?

like image 602
NeoKlojurian Avatar asked Aug 22 '10 14:08

NeoKlojurian


2 Answers

Well, there are actually some pattern matching libraries written for Clojure. Clojure's macros make this sort of thing possible. Matchure is one of the most recent. There are even some stuff for ADTs in contrib.

Disregarding that stuff, the closest thing we have to Haskell's ADTs in core Clojure is the new records and datatypes in Clojure 1.2. But, unless you need the benefits that come from using a record or datatype, you'll usually just use a map. Clojure is a dynamic language, so you wont get static type checking if you use a record and such anyway.

Clojure has "destructuring" which is reminiscent of pattern matching, and is used a lot in idiomatic Clojure. See this and this. The former is an answer by yours truly here on SO. ;p

like image 80
Rayne Avatar answered Sep 19 '22 11:09

Rayne


It depends a bit on what you are trying to do. But assuming the common case of wanting polymorphic behaviour based on data type, protocols are often a good approach:

(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

In this context, the protocol effectively defines the set of operations you want on your ADT, and the records define the possible values of the ADT as well as the polymorphic behaviour for the protocol functions.

like image 21
mikera Avatar answered Sep 17 '22 11:09

mikera