Comparison of programming languages (algebraic data type) explained
This article compares the syntax for defining and instantiating an algebraic data type (ADT), sometimes also referred to as a tagged union, in various programming languages.
Examples of algebraic data types
ATS
In ATS, an ADT may be defined with:[1] [2]
datatype tree = | Empty of | Node of (int, tree, tree)
And instantiated as:val my_tree = Node(42, Node(0, Empty, Empty), Empty)
Additionally in ATS dataviewtypes are the linear type version of ADTs for the purpose of providing in the setting of manual memory management with the convenience of pattern matching.[3] An example program might look like:
(* Alternatively one can use the datavtype keyword *)dataviewtype int_or_string_vt (bool) = | String_vt (true) of string | Int_vt (false) of int
(* Alternatively one can use the vtypedef keyword *)viewtypedef Int_or_String_vt = [b: bool] int_or_string_vt b
fn print_int_or_string (i_or_s: Int_or_String_vt): void = case+ i_or_s of (* ~ indicates i_or_s will be implicitly freed in this case *) | ~String_vt(s) => println!(s) (* @ indicates i_or_s must be explicitly freed in this case *) | @Int_vt(i) => begin $extfcall(void, "fprintf", stdout_ref, "%d\n", i); free@i_or_s; end
implement main0 : void = let val string_hello_world = String_vt "Hello, world!" val int_0 = Int_vt 0in print_int_or_string string_hello_world; print_int_or_string int_0; (* which prints: Hello, world! 0 *)end
Ceylon
In Ceylon, an ADT may be defined with:[4]
abstract class Tree of empty | Node
object empty extends Tree
final class Node(shared Integer val, shared Tree left, shared Tree right) extends Tree
And instantiated as:
value myTree = Node(42, Node(0, empty, empty), empty);
Clean
In Clean, an ADT may be defined with:[5]
Tree = Empty | Node Int Tree Tree
And instantiated as:
myTree = Node 42 (Node 0 Empty Empty) Empty
Coq
In Coq, an ADT may be defined with:[6]
Inductive tree : Type :=| empty : tree| node : nat -> tree -> tree -> tree.
And instantiated as:
Definition my_tree := node 42 (node 0 empty empty) empty.
C++
In C++, an ADT may be defined with:[7]
struct Empty final ;
struct Node final ;
using Tree = std::variant;
And instantiated as:
Tree myTree ;
Dart
In Dart, an ADT may be defined with:[8]
sealed class Tree
final class Empty extends Tree
final class Node extends Tree
And instantiated as:
final myTree = Node(42, Node(0, Empty, Empty), Empty);
Elm
In Elm, an ADT may be defined with:[9]
type Tree = Empty | Node Int Tree Tree
And instantiated as:
myTree = Node 42 (Node 0 Empty Empty) Empty
F#
In F#, an ADT may be defined with:[10]
type Tree = | Empty | Node of int * Tree * Tree
And instantiated as:
let myTree = Node(42, Node(0, Empty, Empty), Empty)
F*
In F*, an ADT may be defined with:[11]
type tree = | Empty : tree | Node : value:nat -> left:tree -> right:tree -> tree
And instantiated as:
let my_tree = Node 42 (Node 0 Empty Empty) Empty
Free Pascal
In Free Pascal (in standard ISO Pascal mode[12]), an ADT may be defined with variant records:[13]
program MakeTree;
type TreeKind = (Empty, Node); PTree = ^Tree; Tree = record case Kind: TreeKind of Empty: ; Node: (Value: Integer; Left, Right: PTree;); end;
And instantiated as:
var MyTree: PTree;
begin new(MyTree, Node); with MyTree^ do begin Value := 42; new(Left, Node); with Left^ do begin Value := 0; new(Left, Empty); new(Right, Empty); end; new(Right, Empty); end;end.
Haskell
In Haskell, an ADT may be defined with:[14]
data Tree = Empty | Node Int Tree Tree
And instantiated as:
myTree = Node 42 (Node 0 Empty Empty) Empty
Haxe
In Haxe, an ADT may be defined with:[15]
enum Tree
And instantiated as:
var myTree = Node(42, Node(0, Empty, Empty), Empty);
Hope
In Hope, an ADT may be defined with:[16]
data tree
empty ++ node (num # tree # tree);
And instantiated as:
dec mytree : tree;--- mytree <= node (42, node (0, empty, empty), empty);
Idris
In Idris, an ADT may be defined with:[17]
data Tree = Empty | Node Nat Tree Tree
And instantiated as:
myTree : TreemyTree = Node 42 (Node 0 Empty Empty) Empty
Java
In Java, an ADT may be defined with:[18]
sealed interface Tree
And instantiated as:
var myTree = new Tree.Node(42, new Tree.Node(0, new Tree.Empty, new Tree.Empty), new Tree.Empty);
Julia
In Julia, an ADT may be defined with:[19]
struct Emptyend
struct Node value::Int left::Union right::Unionend
const Tree = Union
And instantiated as:
mytree = Node(42, Node(0, Empty, Empty), Empty)
Kotlin
In Kotlin, an ADT may be defined with:[20]
sealed class Tree
And instantiated as:
val myTree = Tree.Node(42, Tree.Node(0, Tree.Empty, Tree.Empty), Tree.Empty,)
Limbo
In Limbo, an ADT may be defined with:[21]
Tree: adt ;
And instantiated as:
myTree := ref Tree.Node(42, ref Tree.Node(0, ref Tree.Empty, ref Tree.Empty), ref Tree.Empty);
Mercury
In Mercury, an ADT may be defined with:[22]
- type tree ---> empty ; node(int, tree, tree).
And instantiated as:
- func my_tree = tree.my_tree = node(42, node(0, empty, empty), empty).
Miranda
In Miranda, an ADT may be defined with:[23]
tree ::= Empty | Node num tree tree
And instantiated as:
my_tree = Node 42 (Node 0 Empty Empty) Empty
Nemerle
In Nemerle, an ADT may be defined with:[24]
variant Tree
And instantiated as:
def myTree = Tree.Node(42, Tree.Node(0, Tree.Empty, Tree.Empty), Tree.Empty,);
Nim
In Nim, an ADT may be defined with:[25]
type TreeKind = enum tkEmpty tkNode
Tree = ref TreeObj
TreeObj = object case kind: TreeKind of tkEmpty: discard of tkNode: value: int left, right: Tree
And instantiated as:
let myTree = Tree(kind: tkNode, value: 42, left: Tree(kind: tkNode, value: 0, left: Tree(kind: tkEmpty), right: Tree(kind: tkEmpty)), right: Tree(kind: tkEmpty))
OCaml
In OCaml, an ADT may be defined with:[26]
type tree = | Empty | Node of int * tree * tree
And instantiated as:
let my_tree = Node (42, Node (0, Empty, Empty), Empty)
Opa
In Opa, an ADT may be defined with:[27]
type tree = or
And instantiated as:
my_tree =
OpenCog
In OpenCog, an ADT may be defined with:[28]
PureScript
In PureScript, an ADT may be defined with:
data Tree = Empty | Node Int Tree Tree
And instantiated as:
myTree = Node 42 (Node 0 Empty Empty) Empty
Python
In Python, an ADT may be defined with:[29]
from __future__ import annotationsfrom dataclasses import dataclass
@dataclassclass Empty: pass
@dataclassclass Node: value: int left: Tree right: Tree
Tree = Empty | Node
And instantiated as:
my_tree = Node(42, Node(0, Empty, Empty), Empty)
Racket
In Typed Racket, an ADT may be defined with:[30]
(struct Empty)(struct Node ([value : Integer] [left : Tree] [right : Tree]))(define-type Tree (U Empty Node))
And instantiated as:
(define my-tree (Node 42 (Node 0 (Empty) (Empty)) (Empty)))
Reason
Reason
In Reason, an ADT may be defined with:[31]
type Tree = | Empty | Node(int, Tree, Tree);
And instantiated as:
let myTree = Node(42, Node(0, Empty, Empty), Empty);
ReScript
In ReScript, an ADT may be defined with:[32]
type rec Tree = | Empty | Node(int, Tree, Tree)
And instantiated as:
let myTree = Node(42, Node(0, Empty, Empty), Empty)
Rust
In Rust, an ADT may be defined with:[33]
enum Tree
And instantiated as:
let my_tree = Tree::Node(42, Box::new(Tree::Node(0, Box::new(Tree::Empty), Box::new(Tree::Empty)), Box::new(Tree::Empty),);
Scala
Scala 2
In Scala 2, an ADT may be defined with:
sealed abstract class Tree extends Product with Serializable
object Tree
And instantiated as:
val myTree = Tree.Node(42, Tree.Node(0, Tree.Empty, Tree.Empty), Tree.Empty)
Scala 3
In Scala 3, an ADT may be defined with:[34]
enum Tree: case Empty case Node(value: Int, left: Tree, right: Tree)
And instantiated as:
val myTree = Tree.Node(42, Tree.Node(0, Tree.Empty, Tree.Empty), Tree.Empty)
Standard ML
In Standard ML, an ADT may be defined with:[35]
datatype tree = EMPTY | NODE of int * tree * tree
And instantiated as:
val myTree = NODE (42, NODE (0, EMPTY, EMPTY), EMPTY)
Swift
In Swift, an ADT may be defined with:[36]
enum Tree
And instantiated as:
let myTree: Tree = .node(42, .node(0, .empty, .empty), .empty)
TypeScript
In TypeScript, an ADT may be defined with:[37]
type Tree = | | ;
And instantiated as:
const myTree: Tree = ;
Visual Prolog
In Visual Prolog, an ADT may be defined with:[38]
domains tree = empty; node(integer, tree, tree).
And instantiated as:
constants my_tree : tree = node(42, node(0, empty, empty), empty).
Notes and References
- Web site: Recursively Defined Datatypes.
- Web site: Example: Binary Search Tree.
- Web site: Dataviewtypes as Linear Datatypes.
- Web site: Eclipse Ceylon: Union, intersection, and enumerated types. 2021-11-29. ceylon-lang.org. https://web.archive.org/web/20221226095943/https://ceylon-lang.org/documentation/1.3/tour/types/#enumerated_types. 2022-12-26.
- Web site: Clean 2.2 Ref Man. 2021-11-29. clean.cs.ru.nl.
- Web site: Inductive types and recursive functions — Coq 8.14.1 documentation. 2021-11-30. coq.inria.fr.
- Web site: std::variant - cppreference.com. 2021-12-04. en.cppreference.com.
- Web site: Patterns . 2023-09-28 . dart.dev . en.
- Web site: Custom Types · An Introduction to Elm. 2021-11-29. guide.elm-lang.org.
- Web site: cartermp. Discriminated Unions - F#. 2021-11-29. docs.microsoft.com. en-us.
- Web site: Inductive types and pattern matching — Proof-Oriented Programming in F* documentation. 2021-12-06. www.fstar-lang.org.
- Web site: Mode iso . 2024-05-26 . wiki.freepascal.org.
- Web site: Record types . 2021-12-05 . www.freepascal.org.
- Web site: 4 Declarations and Bindings. 2021-12-07. www.haskell.org.
- Web site: Enum Instance. 2021-11-29. Haxe - The Cross-platform Toolkit.
- Web site: 2011-08-10. Defining your own data types. 2021-12-03. https://web.archive.org/web/20110810074239/http://www.soi.city.ac.uk/~ross/Hope/hope_tut/node18.html. 2011-08-10.
- Web site: Types and Functions — Idris2 0.0 documentation. 2021-11-30. idris2.readthedocs.io.
- Web site: JEP 409: Sealed Classes. 2021-12-05. openjdk.java.net.
- Web site: Types · The Julia Language. 2021-12-03. docs.julialang.org.
- Web site: Sealed classes Kotlin. 2021-11-29. Kotlin Help. en-US.
- Book: Stanley-Marbell, Phillip. Inferno Programming with Limbo. Wiley. 2003. 978-0470843529. 67–71. English.
- Web site: The Mercury Language Reference Manual: Discriminated unions. 2021-12-07. www.mercurylang.org.
- Web site: An Overview of Miranda. 2021-12-04. www.cs.kent.ac.uk. https://web.archive.org/web/20211204101128/https://www.cs.kent.ac.uk/people/staff/dat/miranda/Overview.html#User. 2021-12-04.
- Web site: Basic Variants · rsdn/nemerle Wiki. 2021-12-03. GitHub. en.
- Web site: Nim Manual. 2021-11-29. nim-lang.org.
- Web site: OCaml - The OCaml language. 2021-12-07. ocaml.org.
- Web site: The type system · MLstate/opalang Wiki. 2021-12-07. GitHub. en.
- Web site: Type constructor - OpenCog. 2021-12-07. wiki.opencog.org.
- Web site: PEP 604 – Allow writing union types as X Y peps.python.org . 2024-11-05 . Python Enhancement Proposals (PEPs) . en.
- Web site: 2 Beginning Typed Racket. 2021-12-04. docs.racket-lang.org.
- Web site: Variants · Reason. 2021-11-30. reasonml.github.io. en.
- Web site: Variant ReScript Language Manual. 2021-11-30. ReScript Documentation.
- Web site: enum - Rust. 2021-11-29. doc.rust-lang.org.
- Web site: Algebraic Data Types. 2021-11-29. Scala Documentation.
- Web site: Defining datatypes. 2021-12-01. homepages.inf.ed.ac.uk.
- Web site: Enumerations — The Swift Programming Language (Swift 5.5). 2021-11-29. docs.swift.org.
- Web site: Documentation - TypeScript for Functional Programmers. 2021-11-29. www.typescriptlang.org. en.
- Web site: Language Reference/Domains - wiki.visual-prolog.com. 2021-12-07. wiki.visual-prolog.com.