この記事では、さまざまなプログラミング言語における代数的データ型(ADT)、別名タグ付き共用体の定義とインスタンス化の構文を比較します。
ATSでは、ADTは次のように定義できます。[ 1 ] [ 2 ]
データ型tree = |空( ) |ノード( int 、tree 、tree )そして、以下のようにインスタンス化されます。
val my_tree = Node ( 42 , Node ( 0 , Empty , Empty ), Empty )さらに、ATSのデータビュータイプは、手動メモリ管理の環境でパターンマッチングの利便性を提供するために、ADTの線形型バージョンです。 [ 3 ]プログラムの例は次のようになります。
(* または、datavtype キーワードを使用することもできます *) dataviewtype int_or_string_vt ( bool ) = | String_vt ( true ) of string | Int_vt ( false ) of int(* または、vtypedef キーワードを使用することもできます *) viewtypedef Int_or_String_vt = [ b : bool ] int_or_string_vt bfn print_int_or_string ( i_or_s : Int_or_String_vt ): void = case + i_or_s of (* ~ は、この場合 i_or_s が暗黙的に解放されることを示します *) | ~ String_vt ( s ) => println !( s ) (* @ は、この場合 i_or_s を明示的に解放する必要があることを示します *) | @ Int_vt ( i ) => begin $ extfcall ( void , "fprintf" , stdout_ref , "%d \n " , i ); free @ i_or_s ; endimplementmain0():void=letvalstring_hello_world=String_vt"Hello, world!"valint_0=Int_vt0inprint_int_or_stringstring_hello_world;print_int_or_stringint_0;(* which prints: Hello, world! 0 *)endIn Ceylon, an ADT may be defined with:[4]
abstractclassTree()ofempty|Node{}objectemptyextendsTree(){}finalclassNode(sharedIntegerval,sharedTreeleft,sharedTreeright)extendsTree(){}And instantiated as:
valuemyTree=Node(42,Node(0,empty,empty),empty);In Clean, an ADT may be defined with:[5]
::Tree=Empty|NodeIntTreeTreeAnd instantiated as:
myTree=Node42(Node0EmptyEmpty)EmptyIn C++, an ADT may be defined with:[6]
structEmptyfinal{};structNodefinal{intvalue;std::unique_ptr<std::variant<Empty,Node>>left;std::unique_ptr<std::variant<Empty,Node>>right;};usingTree=std::variant<Empty,Node>;And instantiated as:
Tree myTree { Node { 42 , std :: make_unique < Tree > ( Node { 0 , std :: make_unique < Tree > (), std :: make_unique < Tree > () }), std :: make_unique < Tree > () } };Dartでは、ADTは次のように定義できます。[ 7 ]
sealed class Tree {}final class Empty extends Tree {}final class Node extends Tree { final int value ; final Tree left , right ;ノード( this.value , this.left , this.right ) ; }そして、以下のようにインスタンス化されます。
final myTree = Node ( 42 , Node ( 0 , Empty (), Empty ()), Empty ());Elmでは、ADTは次のように定義できます。[ 8 ]
type Tree =空| Node Int Tree Treeそして、以下のようにインスタンス化されます。
myTree =ノード42 (ノード0空空)空F#では、ADTは次のように定義できます。[ 9 ]
type Tree = | Empty | Node of int * Tree * Treeそして、以下のようにインスタンス化されます。
let myTree = Node ( 42 , Node ( 0 , Empty , Empty ), Empty )F* では、ADT は次のように定義できます。[ 10 ]
type tree = | Empty : tree | Node : value : nat -> left : tree -> right : tree -> treeそして、以下のようにインスタンス化されます。
let my_tree = Node 42 ( Node 0 Empty Empty ) EmptyFree Pascal (標準 ISO Pascal モード[ 11 ]では、ADT はバリアント レコードで定義できます。[ 12 ]
{$mode ISO}プログラムMakeTree ;type TreeKind = ( Empty , Node ) ; PTree = ^ Tree ; Tree = record case Kind : TreeKind of Empty : () ; Node : ( Value : Integer ; Left , Right : PTree ; ) ; end ;そして、以下のようにインスタンス化されます。
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では、ADTは次のように定義できます。[ 13 ]
データツリー=空|ノード整数ツリーツリーそして、以下のようにインスタンス化されます。
myTree =ノード42 (ノード0空空)空Haxeでは、ADTは次のように定義できます。[ 14 ]
enum Tree { Empty ; Node ( value : Int , left : Tree , right : Tree ); }そして、以下のようにインスタンス化されます。
var myTree = Node ( 42 , Node ( 0 , Empty , Empty ), Empty );Hopeでは、ADTは次のように定義される可能性があります。[ 15 ]
データツリー==空++ノード( num #ツリー#ツリー);そして、以下のようにインスタンス化されます。
dec mytree : ツリー; --- mytree <= node (42, node (0, empty, empty), empty); Idrisでは、ADTは次のように定義できます。[ 16 ]
データツリー=空|ノードナットツリーツリーそして、以下のようにインスタンス化されます。
myTree : Tree myTree = Node 42 ( Node 0空空)空Javaでは、ADTは次のように定義できます。[ 17 ]
sealed interface Tree { record Empty () implements Tree {} record Node ( int value , Tree left , Tree right ) implements Tree {} }そして、以下のようにインスタンス化されます。
var myTree = new Tree.Node ( 42 , new Tree.Node ( 0 , new Tree.Empty ( ) , new Tree.Empty ( ) ) , new Tree.Empty ( ) ) ;Juliaでは、ADTは次のように定義できます。[ 18 ]
構造体空の端struct Node value :: Int left :: Union { Empty , Node } right :: Union { Empty , Node } endconst Tree = Union { Empty , Node }そして、以下のようにインスタンス化されます。
mytree = Node ( 42 , Node ( 0 , Empty (), Empty ()), Empty ())Kotlinでは、ADTは次のように定義できます。[ 19 ]
sealed class Tree { object Empty : Tree () data class Node ( val value : Int , val left : Tree , val right : Tree ) : Tree () }そして、以下のようにインスタンス化されます。
val myTree = Tree.Node ( 42 , Tree.Node ( 0 , Tree.Empty , Tree.Empty ) , Tree.Empty , )Limboでは、ADTは次のように定義される可能性があります。[ 20 ]
Tree : adt { pick { Empty => Node => value : int ; left : ref Tree ; right : ref Tree ; } };そして、以下のようにインスタンス化されます。
myTree : = ref Tree.Node ( 42 , ref Tree.Node ( 0 , ref Tree.Empty ( ) , ref Tree.Empty ( ) ) , ref Tree.Empty ( ) ) ;Mercuryでは、ADTは次のように定義できます。[ 21 ]
:- type tree ---> empty ; node ( int , tree , tree ).そして、以下のようにインスタンス化されます。
:- func my_tree = tree . my_tree = node ( 42 , node ( 0 , empty , empty ), empty ).ミランダでは、ADTは次のように定義される可能性がある。[ 22 ]
tree ::=空|ノード番号tree treeそして、以下のようにインスタンス化されます。
my_tree =ノード42 (ノード0空空)空ネメルレでは、ADTは次のように定義される可能性がある。[ 23 ]
variantTree{|Empty|Node{value:int;left:Tree;right:Tree;}}And instantiated as:
defmyTree=Tree.Node(42,Tree.Node(0,Tree.Empty(),Tree.Empty()),Tree.Empty(),);In Nim, an ADT may be defined with:[24]
typeTreeKind=enumtkEmptytkNodeTree=refTreeObjTreeObj=objectcasekind:TreeKindoftkEmpty:discardoftkNode:value:intleft,right:TreeAnd instantiated as:
letmyTree=Tree(kind:tkNode,value:42,left:Tree(kind:tkNode,value:0,left:Tree(kind:tkEmpty),right:Tree(kind:tkEmpty)),right:Tree(kind:tkEmpty))In OCaml, an ADT may be defined with:[25]
typetree=|Empty|Nodeofint*tree*treeAnd instantiated as:
letmy_tree=Node(42,Node(0,Empty,Empty),Empty)In Opa, an ADT may be defined with:[26]
type tree ={ empty }or{ node, int value, tree left, tree right }And instantiated as:
my_tree = { node , value : 42 , left : { node, value: 0, left: { empty }, right: { empty } } , right : { empty } }OpenCogのAtomese では、ADTはグラフベースのAtomSpace内で、和型と積型を表すSignatureLinkやTypeChoiceなどの明示的な型コンストラクタを使用して構築されます。バイナリツリーADTは次のように定義できます。[ 27 ]
; "Tree" 合計タイプの選択肢を定義します( TypeChoice ( DefinedTypeNode "Tree" ) ( TypeSetLink ( TypeNode "Empty" ) ( SignatureLink ( TypeNode "Node" ) ( TypeSetLink ( TypeNode "NumberNode" ) ( DefinedTypeNode "Tree" ) ( DefinedTypeNode "Tree" )))))そして、グラフ構造としてインスタンス化されます。
; 次のようなツリー構造をインスタンス化します: Node(42, Node(0, Empty, Empty), Empty) ( Node ( NumberNode "42" ) ( Node ( NumberNode "0" ) ( Empty ) ( Empty )) ( Empty ))PureScriptでは、ADTは次のように定義できます。[ 28 ]
データツリー = 空 | ノード 整数 ツリー ツリーそして、以下のようにインスタンス化されます。
myTree = ノード 42 (ノード 0 空 空) 空Pythonでは、ADTは次のように定義できます。[ 29 ] [ 30 ]
from __future__ import annotations from dataclasses import dataclass@dataclass class Empty : pass@dataclass class Node : value : int left : Tree right : Treeツリー=空|ノードそして、以下のようにインスタンス化されます。
my_tree = Node ( 42 , Node ( 0 , Empty (), Empty ()), Empty ())Typed Racketでは、ADTは次のように定義できます。[ 31 ]
( struct Empty ()) ( struct Node ([ value : Integer ] [ left : Tree ] [ right : Tree ])) ( define-type Tree ( U Empty Node ))そして、以下のようにインスタンス化されます。
( define my-tree ( Node 42 ( Node 0 ( Empty ) ( Empty )) ( Empty )))Reasonでは、ADTは次のように定義できます。[ 32 ]
type Tree = | Empty | Node ( int , Tree , Tree );そして、以下のようにインスタンス化されます。
let myTree = Node ( 42 , Node ( 0 , Empty , Empty ), Empty );ReScriptでは、ADTは次のように定義できます。[ 33 ]
type rec Tree = | Empty | Node ( int , Tree , Tree )そして、以下のようにインスタンス化されます。
let myTree = Node ( 42 , Node ( 0 , Empty , Empty ), Empty )帰納的木:タイプ:= |空:木|ノード: nat ->木->木->木。そして、以下のようにインスタンス化されます。
定義my_tree := node 42 ( node 0 empty empty ) empty 。Rustでは、ADTは次のように定義できます。[ 35 ]
enum Tree { Empty , Node ( i32 , Box < Tree > , Box < Tree > ), }そして、以下のようにインスタンス化されます。
let my_tree = Tree :: Node ( 42 , Box :: new ( Tree :: Node ( 0 , Box :: new ( Tree :: Empty ), Box :: new ( Tree :: Empty )), Box :: new ( Tree :: Empty ), );Scala 2では、ADTは次のように定義できます。
sealed abstract class Tree extends Product with Serializableobject Tree { final case object Empty extends Tree final case class Node ( value : Int , left : Tree , right : Tree ) extends Tree }そして、以下のようにインスタンス化されます。
val myTree = Tree.Node ( 42 , Tree.Node ( 0 , Tree.Empty , Tree.Empty ) , Tree.Empty )Scala 3 では、ADT は次のように定義できます。[ 36 ]
enum Tree : case Empty case Node ( value : Int , left : Tree , right : Tree )そして、以下のようにインスタンス化されます。
val myTree = Tree.Node ( 42 , Tree.Node ( 0 , Tree.Empty , Tree.Empty ) , Tree.Empty )標準MLでは、ADTは次のように定義できます。[ 37 ]
データ型tree = EMPTY | int * tree * treeのNODEそして、以下のようにインスタンス化されます。
val myTree = NODE ( 42 , NODE ( 0 , EMPTY , EMPTY ), EMPTY )Swiftでは、ADTは次のように定義できます。[ 38 ]
enum Tree { case empty indirect case node ( Int , Tree , Tree ) }そして、以下のようにインスタンス化されます。
let myTree : Tree = .node ( 42 , .node ( 0 , .empty , .empty ) , .empty )TypeScriptでは、ADTは次のように定義できます。[ 39 ]
type Tree = | { kind : "empty" } | { kind : "node" ; value : number ; left : Tree ; right : Tree };そして、以下のようにインスタンス化されます。
const myTree : Tree = { kind : "node" , value : 42 , left : { kind : "node" , value : 0 , left : { kind : "empty" }, right : { kind : "empty" }, }, right : { kind : "empty" }, };Visual Prologでは、ADTは次のように定義できます。[ 40 ]
ドメインツリー=空;ノード(整数、ツリー、ツリー)。そして、以下のようにインスタンス化されます。
定数my_tree : tree = node ( 42 , node ( 0 , empty , empty ), empty ).Zigでは、ADTは次のように定義できます。[ 41 ]
const Tree = union ( enum ) { empty , node : struct { value : i32 , left : * const Tree , right : * const Tree , }, };そして、以下のようにインスタンス化されます。
const my_tree : Tree = .{ . node = .{ . value = 42 , . left = & .{ . node = .{ . value = 0 , . left = & . empty , . right = & . empty , } }, . right = & . empty , } };