代数データ型は、いくつかのタイプの「もの」から構築できるという点で異なります。たとえば、ツリーには何も(空)、リーフ、またはノードを含めることができます。
data Tree = Empty
| Leaf Int
| Node Tree Tree
Nodeは2つのTreeで構成されているため、代数的なデータ型は再帰的になります。
パターンマッチングにより、代数データ型を型安全性を維持する方法で分解できます。次の深さの実装とそれに相当する擬似コードを検討してください。
depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)
に比べ:
switch on (data.constructor)
case Empty:
return 0
case Leaf:
return 1
case Node:
let l = data.field1
let r = data.field2
return 1 + max (depth l) (depth r)
これには、プログラマが空のツリーでfield1にアクセスしないように、リーフの前に空を大文字にすることを忘れてはならないという欠点があります。同様に、リーフケースは、ノードケースの前に宣言して、フィールド2がリーフでアクセスされないようにする必要があります。したがって、型安全性は言語によって維持されず、プログラマーに追加の認知的負荷を課します。ところで、ウィキペディアのページから直接これらの例を取得しています。
もちろん、ダックタイピング言語は次のようなことができます:
class Empty
def depth
0
end
end
class Leaf
def depth
1
end
end
class Node
attr_accessor :field1, :field2
def depth
1 + [field1.depth, field2.depth].max
end
end
そのため、代数的データ型は、同等のOOPより厳密に優れているわけではありませんが、ソフトウェアを構築する際に動作するさまざまな緊張を提供します。