Các kiểu dữ liệu đại số khác biệt ở chỗ chúng có thể được xây dựng từ một số loại "vật". Chẳng hạn, Cây có thể chứa không có gì (Trống), Lá hoặc Nút.
data Tree = Empty
| Leaf Int
| Node Tree Tree
Do một nút bao gồm hai cây, nên các kiểu dữ liệu đại số có thể được đệ quy.
Khớp mẫu cho phép các kiểu dữ liệu đại số được giải cấu trúc theo cách duy trì sự an toàn của kiểu. Hãy xem xét việc thực hiện độ sâu sau đây và mã giả tương đương của nó:
depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)
so với:
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)
Điều này có nhược điểm là lập trình viên phải nhớ trường hợp rỗng trước Lá để trường1 không được truy cập trên cây rỗng. Tương tự, trường hợp Lá phải được khai báo trước trường hợp Nút để trường 2 không được truy cập trên Lá. Do đó, an toàn kiểu do đó không được duy trì bởi ngôn ngữ mà thay vào đó áp đặt tải nhận thức bổ sung cho lập trình viên. Nhân tiện, tôi lấy các ví dụ này trực tiếp từ các trang wikipedia.
Tất nhiên, một ngôn ngữ gõ vịt có thể làm một cái gì đó như thế này:
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
Vì vậy, các loại dữ liệu đại số có thể không hoàn toàn tốt hơn so với tương đương OOP của chúng, nhưng chúng cung cấp một tập hợp căng thẳng khác nhau để làm việc khi xây dựng phần mềm.