All Projects → stylewarning → Cl Algebraic Data Type

stylewarning / Cl Algebraic Data Type

Licence: bsd-3-clause
Algebraic data types in Common Lisp

Projects that are alternatives of or similar to Cl Algebraic Data Type

Remote Data Ts
RemoteData type
Stars: ✭ 185 (+115.12%)
Mutual labels:  algebraic-data-types, functional-programming
Imtools
Fast and memory-efficient immutable collections and helper data structures
Stars: ✭ 85 (-1.16%)
Mutual labels:  algebraic-data-types, functional-programming
Fluture
🦋 Fantasy Land compliant (monadic) alternative to Promises
Stars: ✭ 2,249 (+2515.12%)
Mutual labels:  algebraic-data-types, functional-programming
Functionaljava
Functional programming in Java
Stars: ✭ 1,472 (+1611.63%)
Mutual labels:  algebraic-data-types, functional-programming
Static Land
Specification for common algebraic structures in JavaScript based on Fantasy Land
Stars: ✭ 699 (+712.79%)
Mutual labels:  algebraic-data-types, functional-programming
Scriptum
A fool's scriptum on functional programming
Stars: ✭ 346 (+302.33%)
Mutual labels:  algebraic-data-types, functional-programming
Poica
🧮 A research programming language on top of C macros
Stars: ✭ 231 (+168.6%)
Mutual labels:  algebraic-data-types, functional-programming
Purify
Functional programming library for TypeScript - https://gigobyte.github.io/purify/
Stars: ✭ 843 (+880.23%)
Mutual labels:  algebraic-data-types, functional-programming
Derive4j
Java 8 annotation processor and framework for deriving algebraic data types constructors, pattern-matching, folds, optics and typeclasses.
Stars: ✭ 511 (+494.19%)
Mutual labels:  algebraic-data-types, functional-programming
Whyhaskellmatters
In this article I try to explain why Haskell keeps being such an important language by presenting some of its most important and distinguishing features and detailing them with working code examples. The presentation aims to be self-contained and does not require any previous knowledge of the language.
Stars: ✭ 418 (+386.05%)
Mutual labels:  algebraic-data-types, functional-programming
Lambda
Functional patterns for Java
Stars: ✭ 737 (+756.98%)
Mutual labels:  algebraic-data-types, functional-programming
Enum Fp
Functional Enum type / Sum type for javascript with simple pattern matching
Stars: ✭ 27 (-68.6%)
Mutual labels:  algebraic-data-types, functional-programming
Desafios
FP Challenges
Stars: ✭ 77 (-10.47%)
Mutual labels:  functional-programming
Omnia
Stars: ✭ 81 (-5.81%)
Mutual labels:  functional-programming
Incompose
A inferno utility belt for function components and higher-order components
Stars: ✭ 76 (-11.63%)
Mutual labels:  functional-programming
Scalaz Plugin
A compiler plugin that will improve on the scala compiler on the assumption that the user is using the Scalazzi-safe subset of Scala.
Stars: ✭ 76 (-11.63%)
Mutual labels:  functional-programming
Dash
Functional programming library for PHP. Inspired by Underscore, Lodash, and Ramda.
Stars: ✭ 84 (-2.33%)
Mutual labels:  functional-programming
Request Compose
Composable HTTP Client
Stars: ✭ 80 (-6.98%)
Mutual labels:  functional-programming
Pfun
Functional, composable, asynchronous, type-safe Python.
Stars: ✭ 75 (-12.79%)
Mutual labels:  functional-programming
Lila
♞ lichess.org: the forever free, adless and open source chess server ♞
Stars: ✭ 10,315 (+11894.19%)
Mutual labels:  functional-programming

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!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].