Tôi đang làm việc trên một trình biên dịch tính toán lambda nhỏ có hệ thống suy luận kiểu Hindley-Milner đang hoạt động và hiện cũng hỗ trợ đệ quy (không phải trong mã được liên kết), mà tôi hiểu là đủ để làm cho nó hoàn chỉnh .
Vấn đề bây giờ là tôi không biết làm thế nào để làm cho nó hỗ trợ danh sách, hoặc liệu nó đã hỗ trợ chúng chưa và tôi chỉ cần tìm cách mã hóa chúng. Tôi muốn có thể xác định chúng mà không cần phải thêm quy tắc mới vào hệ thống loại.
Cách dễ nhất tôi có thể nghĩ về một danh sách x
là một cái gì đó là null
(hoặc danh sách trống) hoặc một cặp chứa cả x
danh sách và danh sách x
. Nhưng để làm điều này, tôi cần có khả năng xác định các cặp và hoặc, mà tôi tin là các loại sản phẩm và tổng.
Có vẻ như tôi có thể định nghĩa các cặp theo cách này:
pair = λabf.fab
first = λp.p(λab.a)
second = λp.p(λab.b)
Vì pair
sẽ có loại a -> (b -> ((a -> (b -> x)) -> x))
, sau khi vượt qua, giả sử, int
và một string
, nó sẽ mang lại một cái gì đó với loại (int -> (string -> x)) -> x
, đó sẽ là đại diện của một cặp int
và string
. Điều làm phiền tôi ở đây là nếu điều đó đại diện cho một cặp, tại sao điều đó không tương đương về mặt logic, cũng không bao hàm mệnh đề int and string
? Tuy nhiên, tương đương với (((int and string) -> x) -> x)
, như thể tôi chỉ có thể có các loại sản phẩm làm tham số cho các chức năng. Câu trả lời nàydường như để giải quyết vấn đề này, nhưng tôi không biết những biểu tượng anh ấy sử dụng có ý nghĩa gì. Ngoài ra, nếu điều này không thực sự mã hóa một loại sản phẩm, tôi có thể làm gì với các loại sản phẩm mà tôi không thể làm với định nghĩa về các cặp ở trên không (xem xét tôi cũng có thể định nghĩa n-tuples theo cách tương tự)? Nếu không, điều này có mâu thuẫn với thực tế là bạn không thể diễn đạt (AFAIK) chỉ sử dụng hàm ý không?
Ngoài ra, làm thế nào về các loại tổng? Tôi có thể bằng cách nào đó mã hóa nó bằng cách chỉ sử dụng loại chức năng? Nếu vậy, điều này sẽ đủ để xác định danh sách? Hoặc nếu không, có cách nào khác để xác định danh sách mà không phải mở rộng hệ thống loại của tôi không? Và nếu không, tôi cần phải thay đổi những gì nếu tôi muốn giữ nó đơn giản nhất có thể?
Xin lưu ý rằng tôi là một lập trình viên máy tính nhưng không phải là nhà khoa học máy tính cũng không phải là nhà toán học và khá tệ trong việc đọc ký hiệu toán học.
Chỉnh sửa: Tôi không chắc tên kỹ thuật của những gì tôi đã triển khai cho đến nay, nhưng tất cả những gì tôi có về cơ bản là mã tôi đã liên kết ở trên, đây là thuật toán tạo ràng buộc sử dụng quy tắc cho các ứng dụng, trừu tượng và biến được thực hiện từ thuật toán Hinley-Milner và sau đó là thuật toán hợp nhất lấy loại chính. Chẳng hạn, biểu thức \a.a
sẽ mang lại kiểu a -> a
và biểu thức \a.(a a)
sẽ đưa ra lỗi kiểm tra xảy ra. Trên hết, không có chính xác một let
quy tắc mà là một hàm dường như có cùng hiệu ứng cho phép bạn xác định các hàm toàn cầu đệ quy như mã giả này:
GetTypeOfGlobalFunction(term, globalScope, nameOfFunction)
{
// Here 'globalScope' contains a list of name-value pair where every value is of class 'ClosedType',
// meaning their type will be cloned before unified in the unification algorithm so that they can be used polymorphically
tempType = new TypeVariable() // Assign a dummy type to `tempType`, say, type 'x'.
// The next line creates an scope with everything in 'globalScope' plus the 'nameOfFunction = tempType' name-value pair
tempScope = new Scope(globalScope, nameOfFunction, tempType)
type = TypeOfTerm(term, tempScope) // Calculate the type of the term
Unify(tempType, type)
return type
// After returning, the code outside will create a 'ClosedType' using the returned type and add it to the global scope.
}
Mã về cơ bản lấy loại thuật ngữ như bình thường, nhưng trước khi thống nhất, nó thêm tên của hàm được định nghĩa với loại giả vào phạm vi loại để có thể sử dụng đệ quy từ bên trong chính nó.
Chỉnh sửa 2: Tôi mới nhận ra rằng tôi cũng cần các kiểu đệ quy mà tôi không có để xác định danh sách như tôi muốn.
let func = \x -> (func x)
) bạn có được những gì tôi có.