thực hiện kiểu suy luận


91

Tôi thấy một số cuộc thảo luận thú vị ở đây về nhập tĩnh và nhập động. Tôi thường thích nhập tĩnh hơn, do kiểm tra kiểu biên dịch, mã được tài liệu hóa tốt hơn, v.v. Tuy nhiên, tôi đồng ý rằng chúng làm lộn xộn mã nếu được thực hiện theo cách Java làm, chẳng hạn.

Vì vậy, tôi sắp bắt đầu xây dựng một ngôn ngữ kiểu hàm của riêng mình và suy luận kiểu là một trong những điều tôi muốn triển khai. Tôi hiểu rằng đó là một chủ đề lớn và tôi không cố gắng tạo ra thứ gì đó chưa từng được thực hiện trước đây, chỉ là tham khảo cơ bản ...

Bất kỳ gợi ý nào về những gì cần đọc sẽ giúp tôi với điều này? Tốt hơn là một cái gì đó thực dụng / thực tế hơn trái ngược với các văn bản lý thuyết phạm trù lý thuyết / lý thuyết kiểu hơn. Nếu có một văn bản thảo luận về triển khai ở đó, với cấu trúc dữ liệu / thuật toán, thì điều đó sẽ rất đáng yêu.


1
Chính xác là câu hỏi tôi đang tìm kiếm, với một số câu trả lời tuyệt vời!
Paul Hollingsworth

Câu trả lời:


90

Tôi nhận thấy các tài nguyên sau hữu ích để hiểu kiểu suy luận, theo thứ tự tăng độ khó:

  1. Chương 30 (Suy luận kiểu) của cuốn sách có sẵn miễn phí PLAI , Ngôn ngữ lập trình: Ứng dụng và diễn giải , phác thảo kiểu suy luận dựa trên thống nhất.
  2. Khóa học mùa hè Phiên dịch các kiểu dưới dạng giá trị trừu tượng trình bày các bộ đánh giá thanh lịch, bộ kiểm tra kiểu, trình tái tạo kiểu và suy luận bằng cách sử dụng Haskell như một ngôn ngữ kim loại.
  3. Chương 7 (Các loại) của cuốn sách EOPL , Cơ bản về Ngôn ngữ Lập trình .
  4. Chương 22 (Tái tạo kiểu) của cuốn sách TAPL , Các kiểu và Ngôn ngữ Lập trình , và các bản reconfullrecon của các triển khai OCaml tương ứng .
  5. Chương 13 (Tái cấu trúc kiểu) của cuốn sách mới DCPL , Các khái niệm thiết kế trong ngôn ngữ lập trình .
  6. Lựa chọn các bài báo học thuật .
  7. TypeInference của trình biên dịch đóng cửa là một ví dụ về phương pháp phân tích luồng dữ liệu để suy luận kiểu, phù hợp hơn với các ngôn ngữ động mà phương pháp Hindler Milner tiếp cận.

Tuy nhiên, vì cách tốt nhất để học là làm, tôi thực sự khuyên bạn nên triển khai kiểu suy luận cho một ngôn ngữ chức năng đồ chơi bằng cách làm bài tập về nhà của khóa học ngôn ngữ lập trình.

Tôi đề xuất hai bài tập về nhà có thể truy cập này trong ML, bạn có thể hoàn thành cả hai bài tập này trong vòng chưa đầy một ngày:

  1. PCF Interpreter ( một giải pháp ) để khởi động.
  2. Suy luận kiểu PCF ( một giải pháp ) để thực hiện thuật toán W cho suy luận kiểu Hindley-Milner.

Các bài tập này là từ một khóa học nâng cao hơn:

  1. Triển khai MiniML

  2. Các loại đa hình, hiện sinh, đệ quy (PDF)

  3. Đánh máy hai hướng (PDF)

  4. Phân loại và Đối tượng (PDF)


2
Có phải chỉ tôi không, hay mô tả PLAI phần lớn không chính xác / không đầy đủ? Bài giảng bổ sung thêm một chút cho nó, nhưng dường như vẫn chưa đủ để nó hoạt động.
Rei Miyasaka

Tôi cũng không thể nhận được thuật toán trong phiên bản 2012 của sách PLAI. Không có thay thế cho danh sách ràng buộc. Thay vào đó, tôi đã triển khai thuật toán suy luận kiểu trong phiên bản 2003-7 của cuốn sách PLAI, nó có vẻ hoạt động tốt hơn và cũng chia tỷ lệ tốt cho đa hình.
heykell

28

Thật không may là phần lớn tài liệu về chủ đề này rất dày đặc. Tôi cũng ở trong vị trí của bạn. Tôi được giới thiệu đầu tiên về chủ đề này từ Ngôn ngữ lập trình: Ứng dụng và Phiên dịch

http://www.plai.org/

Tôi sẽ cố gắng tóm tắt ý tưởng trừu tượng sau đó là các chi tiết mà tôi không thấy rõ ràng ngay lập tức. Đầu tiên, kiểu suy luận có thể được coi là tạo ra và sau đó giải quyết các ràng buộc. Để tạo ràng buộc, bạn đệ quy thông qua cây cú pháp và tạo một hoặc nhiều ràng buộc trên mỗi nút. Ví dụ: nếu nút là+ toán tử, các toán hạng và kết quả đều phải là số. Nút áp dụng một hàm có cùng kiểu với kết quả của hàm, v.v.

Đối với một ngôn ngữ không có let, bạn có thể giải quyết một cách mù quáng các ràng buộc trên bằng cách thay thế. Ví dụ:

(if (= 1 2) 
    1 
    2)

ở đây, chúng ta có thể nói rằng điều kiện của câu lệnh if phải là Boolean, và kiểu của câu lệnh if giống với kiểu của nó thenelsecác mệnh đề. Kể từ khi chúng tôi biết 12 là số, bằng cách thay thế, chúng ta biết ifcâu lệnh là một số.

Nơi mọi thứ trở nên khó chịu và điều mà tôi không thể hiểu được trong một thời gian, đó là giải quyết:

(let ((id (lambda (x) x)))
    (id id))

Ở đây, chúng tôi đã liên kết idvới một hàm trả về bất cứ thứ gì bạn đã truyền vào, hay còn gọi là hàm nhận dạng. Vấn đề là loại tham số của hàm xlà khác nhau trên mỗi cách sử dụng id. Thứ hai idlà một chức năng của loại a -> a, nơi acó thể là bất cứ điều gì. Đầu tiên là loại (a -> a) -> (a -> a). Điều này được gọi là đa hình cho. Chìa khóa là giải quyết các ràng buộc theo một thứ tự cụ thể: đầu tiên giải quyết các ràng buộc cho định nghĩa của id. Đây sẽ là a -> a. Sau đó, các bản sao mới, riêng biệt của loại idcó thể được thay thế vào các ràng buộc cho từng nơi idđược sử dụng, chẳng hạn a2 -> a2a3 -> a3.

Điều đó không được giải thích dễ dàng trong các nguồn trực tuyến. Họ sẽ đề cập đến thuật toán W hoặc M nhưng không đề cập đến cách chúng hoạt động về mặt giải quyết các ràng buộc, hoặc tại sao nó không ngăn cản tính đa hình của let: mỗi thuật toán đó thực thi một thứ tự để giải quyết các ràng buộc.

Tôi thấy tài nguyên này cực kỳ hữu ích để kết hợp Thuật toán W, M và khái niệm chung về tạo và giải quyết ràng buộc lại với nhau. Nó hơi đặc, nhưng tốt hơn nhiều:

http://www.cs.uu.nl/research/techreps/repo/CS-2002/2002-031.pdf

Nhiều giấy tờ khác cũng rất hay:

http://people.cs.uu.nl/bastiaan/papers.html

Tôi hy vọng điều đó sẽ giúp làm sáng tỏ một thế giới có phần âm u.


7

Ngoài Hindley Milner cho ngôn ngữ chức năng, một cách tiếp cận phổ biến khác để suy luận kiểu cho ngôn ngữ động là abstract interpretation.

Ý tưởng của giải thích trừu tượng là viết một trình thông dịch đặc biệt cho ngôn ngữ, thay vì giữ một môi trường có các giá trị cụ thể (1, false, bao đóng), nó hoạt động trên các giá trị trừu tượng, hay còn gọi là kiểu (int, bool, v.v.). Vì nó diễn giải chương trình trên các giá trị trừu tượng, đó là lý do tại sao nó được gọi là thông dịch trừu tượng.

Pysonar2 là một triển khai giải thích trừu tượng thanh lịch cho Python. Nó được Google sử dụng để phân tích các dự án Python. Về cơ bản, nó sử dụng visitor patternđể gửi cuộc gọi đánh giá đến nút AST có liên quan. Hàm khách truy cập transform chấp nhận contextnút hiện tại sẽ được đánh giá và trả về loại nút hiện tại.



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.