For faster navigation, this Iframe is preloading the Wikiwand page for 代数的データ型.

代数的データ型

代数的データ型(だいすうてきデータがた、: algebraic data type)とはプログラミング、特に関数型プログラミング型システムにおいて使われるデータ型である。それぞれの代数的データ型のには、1個以上のコンストラクタがあり、各コンストラクタには0個以上の引数がある。

代数的データ型の値(データ)の感覚的な説明としては、引数で与えられた他のデータ型の値を、コンストラクタで包んだようなもの、である。コンストラクタに引数がある代数データ型は複合型(他のデータ型を組み合わせて形成する型)である。

概要

[編集]

Haskellにおける、葉に整数型の値を持つ(分岐は部分木しか持たない)、二分木の例で説明する。以下のようなdata宣言で、データ型を宣言する。

data Node = Leaf Integer | Branch Node Node
  deriving (Show)  -- 表示させて確認するために付加してあるもので、必須ではない。

この宣言でNodeという名前の型を宣言している(Haskellでは型名の先頭は大文字でなければならない)。縦棒("|")で区切って、各コンストラクタによる形を並べる。LeafとBranchはコンストラクタ(データコンストラクタ)である。コンストラクタLeafは1個のIntegerを引数として取り、Branchは2個のNodeを引数として取る(再帰データ型の例にもなっている)。Haskellではコンストラクタの名前も、先頭は大文字でなければならない(ここでは避けたが、型とコンストラクタに同じ名前を使っても構わない)。

Haskellインタプリタghciで、この型の値を入力し表示させた例を示す。

*Main> Leaf 1
Leaf 1
*Main> Branch (Branch (Leaf 1) (Leaf 2)) (Branch (Leaf 3) (Leaf 4))
Branch (Branch (Leaf 1) (Leaf 2)) (Branch (Leaf 3) (Leaf 4))

中のデータにアクセスするにはパターンマッチングを使う。ここで定義した型の木の深さを返す関数の例で次に示す。

depth tree = case tree of
  Leaf _     -> 1
  Branch a b -> 1 + max (depth a) (depth b)

応用

[編集]

基本的な代数データ型としては、多くの関数型言語において、言語組み込みのリスト型が用意されており、空リストのためのコンストラクタに相当するリテラルと、追加したい要素と残りのリストを引数に取るコンストラクタ(Lispのen:cons)に相当する、中置記法風のコンストラクタ( ":" など)が言語組み込みで用意されている。

代数的データ型の特殊な例として、直積型(1つのコンストラクタだけを持つ)と列挙型(引数なしの多くのコンストラクタを持つ)がある。

前述の二分木の例において、コンストラクタLeafは Integer -> Node という型を、コンストラクタBranchは Node -> Node -> Node という型を持つ。型のみを見た場合、関数と同じ型をしている。しかし、関数とは違いコンストラクタは単にそこにあるだけのものであり、評価(実行)されるものではなく、オブジェクト指向言語におけるコンストラクタとは異なる。式として見た場合、関数に引数を適用する式は簡約可能だが、コンストラクタによる式は全体としてはそれ以上簡約できない、値をあらわす式である。

関数型言語で抽象データ型を実現する手法のひとつに、モジュールシステムによるスコープ制限を利用して、コンストラクタを掩蔽し、型のみを公開する、という手法がある。データコンストラクタそのものの代わりに、相当する引数をとって、目的の型の値を返すような、コンストラクタを抽象化した関数を定義し、そちらの関数を公開する。この関数が、オブジェクト指向言語におけるコンストラクタに相当する。

他の言語での例

[編集]

OCamlではヴァリアント型と言い、前述の二分木と同等のデータ型は、次のように書く。

 type node = Leaf of int | Branch of node * node

また、伝統的なMLではdatatypeというキーワードを使う。いずれも、ofの後に1個しか型を指定できないので、Branchのように組み込みの直積型であるタプルを併用する必要がある。MLでもコンストラクタの先頭は大文字だが、型名の先頭は小文字である。

Haskellの場合と同様にして、インタプリタ上で値を作る例と深さを返す関数の例を示す。

# Leaf 1;;
- : node = Leaf 1
# Branch (Branch (Leaf 1, Leaf 2), Branch (Leaf 3, Leaf 4));;
- : node = Branch (Branch (Leaf 1, Leaf 2), Branch (Leaf 3, Leaf 4))
let rec depth tree = match tree with
  Leaf _        -> 1
| Branch (a, b) -> 1 + max (depth a) (depth b)

Visual Prologでは次のように書く。

 domains
 tree =
 empty();
 leaf(integer Leaf);
 node(tree Left, tree Right).

この例では、leafとnodeの他に、空の木を示すemptyがある。

理論

[編集]

集合論において代数的データ型と等価なものとして直和がある。この集合の各元はタグ(コンストラクタと等価)とそのタグに対応する型のオブジェクト(コンストラクタの引数と等価)で構成される。

一般に代数的データ型は直積型の総和であり、再帰的に定義されることもある。各コンストラクタは直積型のタグとなって他と区別されるか、1つしかコンストラクタがない場合は、そのデータ型自体が直積型となる。さらにコンストラクタの引数の型が直積型の要素となる。引数のないコンストラクタは空に対応する。データ型が再帰的であるなら、その直積型の総和は再帰データ型となり、各コンストラクタによって再帰データ型が構成される。

例えば、以下のような Haskell のデータ型

  data List a = Nil | Cons a (List a)

型理論的に表すと次のようになる。

コンストラクタは次のようになる。


この Haskell の List 型を型理論の別の形式で表すと、次のようになる。

が2つの定義で順序が入れ替わっている点に注意されたい。前者の形式は再帰型を本体とする型関数の定義であり、後者は型の再帰関数定義である。型変数 は、これが のような基本型ではなく関数型であることを示している( はギリシャ文字で "f" に相当する)。また、型本体の中の引数型 に関数 を適用しなければならない。

List の例の用途から考えると、これら2つの定式化に大きな違いはないが、後者の形式は「入れ子データ型; nested data type」と呼ばれる表現を可能とする。入れ子データ型とは、オリジナルとパラメータ的に異なる再帰型を派生させるものである。詳しくは、 Richard Bird、Lambert Meertens、Ross Paterson らの研究を参照されたい。

参考文献

[編集]

この記事は2008年11月1日以前にFree On-line Dictionary of Computingから取得した項目の資料を元に、GFDL バージョン1.3以降の「RELICENSING」(再ライセンス) 条件に基づいて組み込まれている。

{{bottomLinkPreText}} {{bottomLinkText}}
代数的データ型
Listen to this article

This browser is not supported by Wikiwand :(
Wikiwand requires a browser with modern capabilities in order to provide you with the best reading experience.
Please download and use one of the following browsers:

This article was just edited, click to reload
This article has been deleted on Wikipedia (Why?)

Back to homepage

Please click Add in the dialog above
Please click Allow in the top-left corner,
then click Install Now in the dialog
Please click Open in the download dialog,
then click Install
Please click the "Downloads" icon in the Safari toolbar, open the first download in the list,
then click Install
{{::$root.activation.text}}

Install Wikiwand

Install on Chrome Install on Firefox
Don't forget to rate us

Tell your friends about Wikiwand!

Gmail Facebook Twitter Link

Enjoying Wikiwand?

Tell your friends and spread the love:
Share on Gmail Share on Facebook Share on Twitter Share on Buffer

Our magic isn't perfect

You can help our automatic cover photo selection by reporting an unsuitable photo.

This photo is visually disturbing This photo is not a good choice

Thank you for helping!


Your input will affect cover photo selection, along with input from other users.

X

Get ready for Wikiwand 2.0 🎉! the new version arrives on September 1st! Don't want to wait?