Đa hình cấp cao hơn các loại không có hộp


10

Tôi có một ngôn ngữ trong đó các loại được bỏ hộp theo mặc định, với loại suy luận dựa trên Hindley Kẻ Milner. Tôi muốn thêm đa hình cấp cao hơn, chủ yếu để làm việc với các loại tồn tại.

Tôi nghĩ rằng tôi hiểu cách kiểm tra các loại này, nhưng tôi không biết phải làm gì khi biên dịch. Hiện tại, tôi biên dịch các định nghĩa đa hình bằng cách tạo các chuyên môn, giống như các mẫu C ++, để chúng có thể hoạt động với các giá trị không được đóng hộp. Ví dụ, đưa ra một định nghĩa về f<T>, nếu chương trình chỉ gọi f<Int32>f<Char>, thì chỉ những chuyên ngành đó mới xuất hiện trong chương trình được biên dịch. (Hiện tại tôi đang giả sử biên dịch toàn bộ chương trình.)

Nhưng khi truyền một hàm đa hình như một đối số, tôi không thấy làm thế nào tôi có thể tạo ra chuyên môn đúng, bởi vì hàm này có thể được chọn trong thời gian chạy. Tôi không có lựa chọn nào khác ngoài việc sử dụng một đại diện đóng hộp? Hoặc có một cách xung quanh vấn đề?

Suy nghĩ đầu tiên của tôi là bằng cách nào đó mã hóa rank- n đa hình như bậc 1, nhưng tôi không tin nó có thể nói chung bởi vì một công thức trong logic mang tính xây dựng không nhất thiết phải có một hình thức bình thường prenex.


Một cách khác là giảm số lượng quyền anh cần thiết bằng cách lưu trữ ảnh bitmap mà đối số của hàm và từ trong bộ nhớ là con trỏ. Sau đó, một hàm / cấu trúc đa hình thực sự là đa hình trên một con trỏ hoặc một từ dữ liệu tùy ý và các cấu trúc có thể lưu trữ trường cuối cùng của chúng (ngay cả khi nó là đa hình). Các bitmap đó cũng có thể được sử dụng bởi GC để tránh sự cần thiết của từ khóa cho các loại không tổng.
fread2281

@ fread2281: Tôi thực sự đã từng làm một cái gì đó như thế trong một phiên bản cũ hơn của ngôn ngữ. Tôi hiện không tạo thẻ cho các loại không tổng và không có GC. Tôi nghĩ rằng nó cũng tương thích với phương pháp của Neel K.
Jon Purdy

Câu trả lời:


6

Tôi đã nghĩ một chút về điều này. Vấn đề chính là nói chung, chúng ta không biết giá trị của loại đa hình lớn đến mức nào. Nếu bạn không có thông tin này, bạn phải lấy nó bằng cách nào đó. Monomorp4ation lấy thông tin này cho bạn bằng cách chuyên đi đa hình. Quyền anh có được thông tin này cho bạn bằng cách đưa mọi thứ vào một đại diện có kích thước đã biết.

Một cách khác thứ ba là theo dõi thông tin này trong các loại. Về cơ bản, những gì bạn có thể làm là giới thiệu một loại khác nhau cho từng kích thước dữ liệu và sau đó các hàm đa hình có thể được xác định trên tất cả các loại có kích thước cụ thể. Tôi sẽ phác thảo một hệ thống như vậy dưới đây.

Kindsκ::=nType constructorsA::=a:κ.A|α|A×B|A+B|AB|refA|Pad(k)|μα:κ.A

Ở đây, ý tưởng cấp cao là loại của một loại cho bạn biết cần bao nhiêu từ để bố trí một đối tượng trong bộ nhớ. Đối với bất kỳ kích thước nhất định, thật dễ dàng để được đa hình trên tất cả các loại kích thước cụ thể đó. Vì mọi loại - ngay cả loại đa hình - vẫn có kích thước đã biết, việc biên dịch không khó hơn so với C.

Các quy tắc sắp xếp biến tiếng Anh này thành toán học và sẽ trông giống như thế này:

α:nΓΓα:nΓ,α:nA:mΓα:n.A:m
ΓA:nΓB:mΓA×B:n+mΓA:nΓB:nΓA+B:n+1
ΓA:mΓB:nΓAB:1ΓA:nΓrefA:1
ΓPad(k):kΓ,α:nA:nΓμα:n.A:n

Vì vậy, bộ định lượng forall yêu cầu bạn đưa ra loại bạn đang sử dụng. Tương tự như vậy, ghép nối là loại cặp không có hộp, chỉ đặt ra một bên cạnh trong bộ nhớ (như kiểu cấu trúc C). Các hiệp hội rời rạc lấy hai giá trị có cùng kích thước và sau đó thêm một từ cho thẻ phân biệt đối xử. Các hàm là các bao đóng, được biểu diễn như bình thường bằng một con trỏ tới bản ghi môi trường và mã.A BA×BAB

Tài liệu tham khảo rất thú vị - con trỏ luôn là một từ, nhưng chúng có thể trỏ đến các giá trị ở bất kỳ kích thước nào. Điều này cho phép các lập trình viên thực hiện đa hình cho các đối tượng tùy ý bằng quyền anh, nhưng không yêu cầu họ làm như vậy. Cuối cùng, một khi các kích thước rõ ràng đang hoạt động, việc giới thiệu một loại đệm, sử dụng không gian nhưng không làm gì cả thường rất hữu ích. (Vì vậy, nếu bạn muốn sử dụng liên kết rời rạc của một int và một cặp int, bạn sẽ cần thêm phần đệm int đầu tiên, để bố cục đối tượng được thống nhất.)

Các kiểu đệ quy có quy tắc hình thành tiêu chuẩn, nhưng lưu ý rằng các lần đệ quy phải có cùng kích thước, điều đó có nghĩa là bạn thường phải dán chúng vào một con trỏ để thực hiện công việc phân loại. Ví dụ, kiểu dữ liệu danh sách có thể được biểu diễn dưới dạng

μα:1.ref(Pad(2)+int×α)

Vì vậy, điều này trỏ đến một giá trị danh sách trống, hoặc một cặp int và một con trỏ đến một danh sách liên kết khác.

Kiểm tra loại cho các hệ thống như thế này cũng không khó lắm; thuật toán trong bài báo ICFP của tôi với Joshua Dunfield, Đánh máy hai chiều hoàn chỉnh và dễ dàng cho Đa hình bậc cao áp dụng cho trường hợp này mà hầu như không có thay đổi.


Thật tuyệt, tôi nghĩ rằng điều này gọn gàng bao gồm trường hợp sử dụng của tôi. Tôi đã nhận thức được việc sử dụng các loại để suy luận về các biểu diễn giá trị (như GHC *so với #), nhưng đã không cân nhắc thực hiện theo cách này. Có vẻ hợp lý để hạn chế các bộ lượng hóa được xếp hạng cao hơn đối với các loại kích thước đã biết và tôi nghĩ rằng điều này cũng sẽ cho phép tôi tạo các chuyên ngành theo kích thước một cách tĩnh mà không cần biết loại thực tế. Bây giờ, thời gian để đọc lại bài báo đó. :)
Jon Purdy

1

Điều này dường như gần với một vấn đề biên dịch hơn là một vấn đề "khoa học máy tính lý thuyết", vì vậy có lẽ bạn nên hỏi những nơi khác.

Trong trường hợp chung, thực sự, tôi nghĩ không có giải pháp nào khác ngoài việc sử dụng một đại diện đóng hộp. Nhưng tôi cũng mong đợi rằng trong thực tế có nhiều lựa chọn thay thế khác nhau, tùy thuộc vào chi tiết cụ thể về tình huống của bạn.

Ví dụ: biểu diễn mức thấp của các đối số không được đóng hộp thường có thể được phân loại thành rất ít lựa chọn thay thế, ví dụ: số nguyên hoặc tương tự, dấu phẩy động hoặc con trỏ. Vì vậy, đối với một hàm f<T>, có thể bạn thực sự chỉ cần tạo 3 triển khai chưa được đóng hộp khác nhau và bạn có thể biểu diễn một đa hình dưới dạng một tuple của 3 hàm đó, vì vậy, khởi tạo T thành Int32 chỉ là chọn phần tử đầu tiên của tuple, ...


Cảm ơn bạn đã giúp đỡ. Tôi thực sự không chắc chắn nên hỏi ở đâu, vì một trình biên dịch trải dài từ lý thuyết cấp cao xuống đến kỹ thuật cấp thấp, nhưng tôi đoán rằng mọi người ở đây sẽ có một số ý tưởng. Trông giống như quyền anh thực sự có thể là cách tiếp cận linh hoạt nhất ở đây. Sau khi đọc câu trả lời của bạn và suy nghĩ về nó nhiều hơn, giải pháp hợp lý duy nhất khác mà tôi có thể đưa ra là từ bỏ một số tính linh hoạt và yêu cầu các đối số đa hình phải được biết một cách tĩnh, ví dụ, bằng cách tự chuyển chúng dưới dạng tham số loại. Đó là sự đánh đổi tất cả các cách xuống. : P
Jon Purdy

4
Câu hỏi của OP chứa các vấn đề TCS hoàn toàn hợp lệ, như cách suy luận kiểu khi Damas-Hindley-Milner được mở rộng với các loại thứ hạng cao hơn. Nói chung, đa hình bậc 2 có suy luận kiểu quyết định nhưng đối với suy luận thứ hạng k> 2 thì không thể xác định được. Liệu hạn chế của Damas-Hindley-Milner có thay đổi điều này hay không, tôi không biết. Cuối cùng, mọi thứ về trình biên dịch hiện đại nên là một phần của TCS, nhưng thường thì không phải vì trình triển khai trình biên dịch đi trước các nhà lý thuyết.
Martin Berger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.