Thật vậy, bạn có thể cho tham số kiểu cây, như trong ví dụ Alexander Poluektov. Đủ đơn giản! Nhưng tại sao lại dừng ở đó? Chúng ta có thể vui hơn một chút. Thay vì chỉ là một cấu trúc đệ quy với dữ liệu đa hình, bạn có thể làm cho cấu trúc đa hình trong đệ quy chính nó!
Đầu tiên, trừu tượng hóa tham chiếu của cây thành chính nó, theo cùng cách trừu tượng hóa tham chiếu đến Int
, thay thế tham chiếu đệ quy bằng thông số mới t
. Điều đó khiến chúng tôi có cấu trúc dữ liệu khá mơ hồ này:
data TNode t a = Empty
| Leaf a
| Node (t a) a (t a)
deriving (Eq, Ord, Show, Read)
Điều này đã được đổi tên thành TNode
tại đây vì nó không thực sự là một cây nữa; chỉ là một kiểu dữ liệu đơn giản. Bây giờ, để thu hồi đệ quy gốc và tạo ra một cây, chúng tôi xoay TNode
xung quanh và ăn nó với bản thân:
newtype Tree a = Tree (TNode Tree a) deriving (Eq, Ord, Show, Read)
Bây giờ chúng ta có thể sử dụng Tree
này đệ quy, mặc dù buồn bã với chi phí của một số sự nói dài giòng thêm, như vậy:
Tree (Node (Tree Empty) 5 (Tree (Leaf 2)))
Vì vậy, điều này cung cấp cho chúng tôi, ngoài việc nhập thêm, bạn hỏi? Đơn giản là chúng tôi đã tách cấu trúc cây cơ bản khỏi cả dữ liệu chứa và phương thức mà dữ liệu được xây dựng và xử lý, cho phép chúng tôi viết các hàm chung chung hơn để xử lý một khía cạnh này.
Ví dụ: chúng tôi có thể trang trí cây có thêm dữ liệu hoặc ghép các thứ thừa vào cây mà không ảnh hưởng đến bất kỳ chức năng cây chung nào.Giả sử chúng ta muốn đặt tên cho mỗi phần của cây:
newtype NameTree a = NameTree (String, TNode NameTree a) deriving (Eq, Ord, Show, Read)
Mặt khác, chúng ta có thể viết chung Logic cây traversal:
toList f t = toList' f (f t) []
where toList' f (Node t1 x t2) xs = toList' f (f t1) (x : toList' f (f t2) xs)
toList' f (Leaf x) xs = x:xs
toList' _ Empty xs = xs
Với một hàm để trích xuất các hiện TNode
từ một cây đệ quy, chúng tôi có thể sử dụng cây này trên bất kỳ cấu trúc nào như vậy:
treeToList = toList (\(Tree t) -> t)
nameTreeToList = toList (\(NameTree (_, t)) -> t)
Tất nhiên, điều này có thể vượt xa những gì bạn đang tìm kiếm, nhưng đó là một hương vị tuyệt vời đa hình và mã chung Haskell cho phép (nay, khuyến khích) một lập trình viên để tạo ra.