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

  1. Web site: Recursively Defined Datatypes.
  2. Web site: Example: Binary Search Tree.
  3. Web site: Dataviewtypes as Linear Datatypes.
  4. 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.
  5. Web site: Clean 2.2 Ref Man. 2021-11-29. clean.cs.ru.nl.
  6. Web site: Inductive types and recursive functions — Coq 8.14.1 documentation. 2021-11-30. coq.inria.fr.
  7. Web site: std::variant - cppreference.com. 2021-12-04. en.cppreference.com.
  8. Web site: Patterns . 2023-09-28 . dart.dev . en.
  9. Web site: Custom Types · An Introduction to Elm. 2021-11-29. guide.elm-lang.org.
  10. Web site: cartermp. Discriminated Unions - F#. 2021-11-29. docs.microsoft.com. en-us.
  11. Web site: Inductive types and pattern matching — Proof-Oriented Programming in F* documentation. 2021-12-06. www.fstar-lang.org.
  12. Web site: Mode iso . 2024-05-26 . wiki.freepascal.org.
  13. Web site: Record types . 2021-12-05 . www.freepascal.org.
  14. Web site: 4 Declarations and Bindings. 2021-12-07. www.haskell.org.
  15. Web site: Enum Instance. 2021-11-29. Haxe - The Cross-platform Toolkit.
  16. 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.
  17. Web site: Types and Functions — Idris2 0.0 documentation. 2021-11-30. idris2.readthedocs.io.
  18. Web site: JEP 409: Sealed Classes. 2021-12-05. openjdk.java.net.
  19. Web site: Types · The Julia Language. 2021-12-03. docs.julialang.org.
  20. Web site: Sealed classes Kotlin. 2021-11-29. Kotlin Help. en-US.
  21. Book: Stanley-Marbell, Phillip. Inferno Programming with Limbo. Wiley. 2003. 978-0470843529. 67–71. English.
  22. Web site: The Mercury Language Reference Manual: Discriminated unions. 2021-12-07. www.mercurylang.org.
  23. 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.
  24. Web site: Basic Variants · rsdn/nemerle Wiki. 2021-12-03. GitHub. en.
  25. Web site: Nim Manual. 2021-11-29. nim-lang.org.
  26. Web site: OCaml - The OCaml language. 2021-12-07. ocaml.org.
  27. Web site: The type system · MLstate/opalang Wiki. 2021-12-07. GitHub. en.
  28. Web site: Type constructor - OpenCog. 2021-12-07. wiki.opencog.org.
  29. Web site: PEP 604 – Allow writing union types as X Y peps.python.org . 2024-11-05 . Python Enhancement Proposals (PEPs) . en.
  30. Web site: 2 Beginning Typed Racket. 2021-12-04. docs.racket-lang.org.
  31. Web site: Variants · Reason. 2021-11-30. reasonml.github.io. en.
  32. Web site: Variant ReScript Language Manual. 2021-11-30. ReScript Documentation.
  33. Web site: enum - Rust. 2021-11-29. doc.rust-lang.org.
  34. Web site: Algebraic Data Types. 2021-11-29. Scala Documentation.
  35. Web site: Defining datatypes. 2021-12-01. homepages.inf.ed.ac.uk.
  36. Web site: Enumerations — The Swift Programming Language (Swift 5.5). 2021-11-29. docs.swift.org.
  37. Web site: Documentation - TypeScript for Functional Programmers. 2021-11-29. www.typescriptlang.org. en.
  38. Web site: Language Reference/Domains - wiki.visual-prolog.com. 2021-12-07. wiki.visual-prolog.com.