Ví dụ về cách kiểu dữ liệu cho phép chúng tôi tồn tại bất kỳ loại nào được cung cấp trong Turner, D.A. (2004-07-28), Total Functional Programming, giáo phái. 3.1, trang 758 trong Quy tắc 2: Loại đệ quy phải hiệp biến "
Hãy làm một ví dụ phức tạp hơn sử dụng Haskell Chúng tôi sẽ bắt đầu với a. "Xấu" kiểu dữ liệu đệ quy
data Bad a = C (Bad a -> a)
.
và xây dựng Y combinator từ nó mà không có bất cứ một sự đệ quy. Điều này có nghĩa rằng có như vậy một kiểu dữ liệu cho phép chúng ta xây dựng bất kỳ loại đệ quy, hoặc sống trong bất kỳ loại bởi một đệ quy vô hạn.
.210
Y Combinator trong giải tích lambda untyped được định nghĩa là
Y = λf.(λx.f (x x)) (λx.f (x x))
Chìa khóa để nó là chúng ta áp dụng x
cho chính nó trong x x
. Trong các ngôn ngữ đã nhập, điều này không thể trực tiếp thực hiện được vì không có loại x
hợp lệ nào có thể có. Nhưng Bad
kiểu dữ liệu của chúng tôi cho phép modulo này thêm/gỡ bỏ các nhà xây dựng:
selfApp :: Bad a -> a
selfApp ([email protected](C x')) = x' x
Lấy x :: Bad a
, chúng ta có thể unwrap constructor của nó và áp dụng các chức năng bên trong để x
riêng của mình. Một khi chúng ta biết làm thế nào để làm điều này, thật dễ dàng để xây dựng các combinator Y:
yc :: (a -> a) -> a
yc f = let fxx = C (\x -> f (selfApp x)) -- this is the λx.f (x x) part of Y
in selfApp fxx
Lưu ý rằng không selfApp
cũng không yc
là đệ quy, không có cuộc gọi đệ quy của một hàm cho chính nó. Việc đệ quy chỉ xuất hiện trong kiểu dữ liệu đệ quy của chúng tôi.
Chúng tôi có thể kiểm tra rằng bộ kết hợp được xây dựng thực sự làm những gì cần. Chúng ta có thể thực hiện một vòng lặp vô hạn:
loop :: a
loop = yc id
hoặc tính giả GCD:
gcd' :: Int -> Int -> Int
gcd' = yc gcd0
where
gcd0 :: (Int -> Int -> Int) -> (Int -> Int -> Int)
gcd0 rec a b | c == 0 = b
| otherwise = rec b c
where c = a `mod` b
Câu trả lời hay. Tôi thích cách tiếp cận thanh lịch này với giải thích lý thuyết của nó (nhúng giải tích lambda chưa được phân loại). Liệu có thể mở rộng nó để nó cho phép đệ quy tùy ý tới ngôn ngữ được đề cập (Agda nói)? –
@ PetrPudlák Vì vậy, tôi chỉ nói chuyện với các viên chức của tôi, những người xa và tốt hơn các nhà lý thuyết loại hơn tôi. Sự đồng thuận là điều này "Bad" sẽ không làm phát sinh một thuật ngữ kiểu 'forall a. a' (đó là những gì bạn thực sự quan tâm; đệ quy chỉ là một phương tiện để đạt được điều đó). Các đối số sẽ đi như thế này: bạn có thể xây dựng một mô hình lý thuyết tập hợp của Agda; sau đó bạn có thể thêm vào mô hình đó một cách giải thích 'Bad' như một tập hợp phần tử đơn; vì vẫn còn các kiểu không có người ở trong mô hình kết quả, không có hàm nào dịch các thuật ngữ 'Bad' lặp thành các điều kiện vòng lặp của một kiểu khác. –