Có một số vấn đề được giải quyết dễ dàng bằng các kiểu dữ liệu đại số, ví dụ như một loại Danh sách có thể được thể hiện rất ngắn gọn như sau:
data ConsList a = Empty | ConsCell a (ConsList a)
consmap f Empty = Empty
consmap f (ConsCell a b) = ConsCell (f a) (consmap f b)
l = ConsCell 1 (ConsCell 2 (ConsCell 3 Empty))
consmap (+1) l
Ví dụ cụ thể này là trong Haskell, nhưng nó sẽ tương tự trong các ngôn ngữ khác với sự hỗ trợ riêng cho các kiểu dữ liệu đại số.
Nó chỉ ra rằng có một ánh xạ rõ ràng đến phân nhóm kiểu OO: kiểu dữ liệu trở thành một lớp cơ sở trừu tượng và mọi hàm tạo dữ liệu trở thành một lớp con cụ thể. Đây là một ví dụ trong Scala:
sealed abstract class ConsList[+T] {
def map[U](f: T => U): ConsList[U]
}
object Empty extends ConsList[Nothing] {
override def map[U](f: Nothing => U) = this
}
final class ConsCell[T](first: T, rest: ConsList[T]) extends ConsList[T] {
override def map[U](f: T => U) = new ConsCell(f(first), rest.map(f))
}
val l = (new ConsCell(1, new ConsCell(2, new ConsCell(3, Empty)))
l.map(1+)
Điều duy nhất cần thiết ngoài phân lớp ngây thơ là một cách để đóng dấu các lớp, tức là một cách để không thể thêm các lớp con vào một hệ thống phân cấp.
Làm thế nào bạn sẽ tiếp cận vấn đề này bằng một ngôn ngữ như C # hoặc Java? Hai khối vấp ngã tôi tìm thấy khi cố gắng sử dụng Kiểu dữ liệu đại số trong C # là:
- Tôi không thể tìm ra loại dưới cùng được gọi trong C # (nghĩa là tôi không thể tìm ra loại gì để đưa vào
class Empty : ConsList< ??? >
) - Tôi không thể tìm ra một cách để đóng dấu
ConsList
sao cho không có lớp con nào có thể được thêm vào hệ thống phân cấp
Điều gì sẽ là cách thành ngữ nhất để triển khai các kiểu dữ liệu đại số trong C # và / hoặc Java? Hoặc, nếu không thể, sự thay thế thành ngữ là gì?