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
Ceylon
In Ceylon, an ADT may be defined with:[1]
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:[2]
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:[3]
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:[4]
struct Empty final ;
struct Node final ;
using Tree = std::variant;
And instantiated as:
Tree myTree ;
Dart
In Dart, an ADT may be defined with:[5]
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:[6]
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:[7]
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:[8]
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[9]), an ADT may be defined with variant records:[10]
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:[11]
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:[12]
enum Tree
And instantiated as:
var myTree = Node(42, Node(0, Empty, Empty), Empty);
Hope
In Hope, an ADT may be defined with:[13]
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:[14]
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:[15]
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:[16]
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:[17]
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:[18]
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:[19]
- 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:[20]
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:[21]
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:[22]
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:[23]
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:[24]
type tree = or
And instantiated as:
my_tree =
OpenCog
In OpenCog, an ADT may be defined with:[25]
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:
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:[26]
(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:[27]
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:[28]
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:[29]
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:[30]
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:[31]
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:[32]
enum Tree
And instantiated as:
let myTree: Tree = .node(42, .node(0, .empty, .empty), .empty)
TypeScript
In TypeScript, an ADT may be defined with:[33]
type Tree = | | ;
And instantiated as:
const myTree: Tree = ;
Visual Prolog
In Visual Prolog, an ADT may be defined with:[34]
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: 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.
- 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: 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.