• Stars
    star
    120
  • Rank 295,983 (Top 6 %)
  • Language
    Common Lisp
  • License
    BSD 3-Clause "New...
  • Created almost 7 years ago
  • Updated almost 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Algebraic data types in Common Lisp

CL-ALGEBRAIC-DATA-TYPE

by Robert Smith

CL-ALGEBRAIC-DATA-TYPE, or ADT, is a library for defining algebraic data types in a similar spirit to Haskell or Standard ML, as well as for operating on them.

We can define ADTs using defdata:

(adt:defdata maybe
  (just t)
  nothing)

which will define a new type maybe, with a unary constructor just, and a nullary constructor nothing. The t represents the data type of that field.

> (just 5)
#.(JUST 5)
> nothing
#.NOTHING

Note that the #. are printed so that they can be read back. This allows them to be used literally in quoted lists, for example.

> '(#.(just 1) #.nothing)
(#.(JUST 1) #.NOTHING)
> (typep (first *) 'maybe)
T

If this is annoying to you, you can set the variable adt:*print-adt-readably* to nil.

We can define our own version of a list via

(adt:defdata liszt
  (kons t liszt)
  knil)

which defines the binary constructor kons and the nullary constructor knil.

> (kons 1 (kons 2 knil))
#.(KONS 1 #.(KONS 2 #.KNIL))

At the end we will define kar and kdr.

For efficiency, we might specify the types more exactly. For a point type that supports rectangular and polar coordinates, which is also mutable, we might have:

(adt:defdata (point :mutable t)
  (rectangular float float)
  (polar float float))

The :mutable option signifies that the data is mutable.

When we have constructed a value, we can extract data out of it using match:

> (let ((pt (rectangular 1.0 2.0)))
    (adt:match point pt
      ((rectangular x y) (+ x y))
      ((polar _ _) nil)))
3.0

If we did not include the polar case, we would get a warning.

> (let ((pt (rectangular 1.0 2.0)))
    (adt:match point pt
      ((rectangular x y) (+ x y))))
; caught WARNING:
;   Non-exhaustive match. Missing cases: (POLAR)
3.0

We can also specify a fall-through:

> (let ((pt (rectangular 1.0 2.0)))
    (adt:match point pt
      ((rectangular x y) (+ x y))
      (_ nil)))
3.0

Since point is mutable, we can efficiently modify its fields using set-data.

> (defun mirror-point! (pt)
    (adt:with-data (rectangular x y) pt
      (adt:set-data pt (rectangular y x))))

> (let ((pt (rectangular 1.0 2.0)))
   (mirror-point! pt)
   (adt:match point pt
     ((rectangular x y) (format t "point is (~A, ~A)" x y))
     (_ nil))

will print point is (2.0, 1.0).

See examples.txt for examples.

Frequently Asked Questions

Q. How do we define kar and kdr for liszt?

A. Easy.

(defun kar (l)
  (adt:match liszt l
    ((kons a _) a)
    (knil knil)))

(defun kdr (l)
  (adt:match liszt l
    ((kons _ b) b)
    (knil knil)))

Q. Can I get the constructors dynamically for a particular ADT?

A. Yes. You can get the constructors and associated arity by calling the get-constructors function, which will return a list of (<constructor> <arity>) pairs. For example, given the liszt example above, we have

> (adt:get-constructors 'liszt)
((KONS 2) (KNIL 0))
T

The second value t represents the fact that the ADT is known and exists.

Q. I have an ADT defined, and I'd like to extend it with another ADT. How can I do that?

A. You can define a new ADT which includes another one. For example, consider the following Boolean ADT.

(adt:defdata bool
  true
  false)

Suppose you wanted to extend this to have a "fuzzy" option, a probability between true and false, specifically a real between 0 and 1 exclusive. We can create a fuzzy-bool which includes the bool type, as well as a unary fuzzy constructor. This is done by the :include option to defdata.

(adt:defdata (fuzzy-bool :include bool)
  (fuzzy (real (0) (1))))

Note that true and false are constructors for both bool and fuzzy-bool, as we can see with get-constructors.

> (adt:get-constructors 'bool)
((TRUE 0) (FALSE 0))
T
> (adt:get-constructors 'fuzzy-bool)
((TRUE 0) (FALSE 0) (FUZZY 1))
T

Q. Can we do parametric ADTs like I can in Haskell?

A. There is no support for it because Lisp doesn't have any useful notion of definable parametric types that aren't aliases of another existing parametric type.

Q. Why doesn't deeper pattern matching work?

A. It's not implemented, but it could be implemented for fields which are themselves algebraic data types. Patches welcome!

More Repositories

1

deprecated-coalton-prototype

Coalton is (supposed to be) a dialect of ML embedded in Common Lisp.
Common Lisp
208
star
2

quickutil

The solution to the Utility Library problem.
Common Lisp
87
star
3

lisp-random

A smattering of random Lisp code by Robert Smith
Common Lisp
66
star
4

cl-permutation

Permutations and permutation groups in Common Lisp.
Common Lisp
48
star
5

formulador

Render math formulas in 2D in your terminal!
Common Lisp
44
star
6

quantum-interpreter

A tiny, self-contained, general-purpose quantum interpreter.
Common Lisp
43
star
7

computable-reals

Arbitrary precision, automatic re-computing real numbers in Common Lisp.
Common Lisp
28
star
8

hypergeometrica

Livin' like it's 1813 (or 1988).
Common Lisp
25
star
9

policy-cond

Common Lisp
15
star
10

callback-heaven

Generating and managing callbacks from C into Heaven (Lisp).
Common Lisp
12
star
11

cl-forest

Unofficial bindings to Rigetti Forest in Common Lisp.
Common Lisp
10
star
12

talks

Talks, notes, slides, etc.
TeX
6
star
13

algebraic-data-library

Common Lisp
5
star
14

instructions

Instructions for various things.
Shell
3
star
15

interface

Common Lisp
2
star
16

arpeggiando

Common Lisp
2
star
17

webapp

An example webapp in Common Lisp using Hunchentoot and stuff.
Common Lisp
2
star
18

compsci-with-robert

Common Lisp
2
star
19

clim-color-picker

Sample, minimal, buildable CLIM app.
Common Lisp
2
star
20

map-set

Common Lisp
2
star
21

big-string

Common Lisp
2
star
22

synonyms

Common Lisp
2
star
23

recur

Common Lisp
1
star
24

parameterized-function

Common Lisp
1
star
25

cadrlogue

A book and media cataloguing system.
Common Lisp
1
star
26

cl-stopwatch

Common Lisp
1
star
27

illogical-pathnames

Common Lisp
1
star
28

maxima

Common Lisp
1
star