Đa hình xếp hạng cao hơn mà không có ứng dụng rõ ràng hoặc phân nhóm?


7

Vì vậy, tôi quen thuộc với hai chiến lược chính là có tính đa hình được xếp hạng cao hơn trong một ngôn ngữ:

  • Tính đa hình kiểu System-F, trong đó các hàm được gõ rõ ràng và việc khởi tạo xảy ra rõ ràng mặc dù ứng dụng kiểu. Các hệ thống này có thể là bắt buộc.
  • Đa hình dựa trên phân loại, trong đó một loại đa hình là một kiểu con của tất cả các tức thời của nó. Để có phân nhóm có thể quyết định, tính đa hình phải là dự đoán. Bài viết này cung cấp một ví dụ về một hệ thống như vậy.

Tuy nhiên, một số ngôn ngữ, như Haskell, có tính đa hình xếp hạng cao hơn mà không có ứng dụng loại rõ ràng.

Sao có thể như thế được? Làm thế nào có thể kiểm tra kiểu "biết" khi nào khởi tạo một loại mà không cần khởi tạo rõ ràng hoặc truyền và không có khái niệm về phân nhóm?

Hoặc, là đánh máy thậm chí có thể quyết định trong một hệ thống như vậy? Đây có phải là trường hợp mà ngôn ngữ như Haskell thực hiện một cái gì đó không thể giải quyết được sẽ xảy ra với hầu hết các trường hợp sử dụng của mọi người.

BIÊN TẬP:

Để rõ ràng, tôi quan tâm đến việc sử dụng , không phải định nghĩa, về các giá trị được đánh máy đa hình.

Ví dụ: giả sử chúng ta có:

f : forall a . a -> a
g : (forall a . a -> a) -> Int
val = (g f, f True, f 'a')

Làm thế nào chúng ta có thể biết rằng chúng ta cần khởi tạo fkhi nó được áp dụng, nhưng không phải khi nó được đưa ra như một đối số?

Hoặc, để tách chúng ta khỏi các loại chức năng:

f : forall a . a
g : (forall a . a) -> Int
val = (g f, f && True, f + 0)

Ở đây, chúng ta thậm chí không thể phân biệt việc sử dụng fnhư áp dụng nó so với việc chuyển nó: nó được khởi tạo khi được truyền dưới dạng đối số &&+, nhưng không g.

Làm thế nào một hệ thống lý thuyết có thể phân biệt hai trường hợp này mà không có quy tắc "bạn có thể chuyển đổi bất kỳ loại đa hình nào sang thể hiện của nó"? Hoặc với một quy tắc như vậy, chúng ta có thể biết khi nào nên áp dụng nó, để giữ tính quyết định?


Haskell sẽ không bao giờ suy ra một polytype cho một biến loại, trừ khi nó được cung cấp rõ ràng bởi người dùng. Ví dụ: \f -> (f True, f 'a')sẽ không kiểm tra loại, ngay cả khi có thể được chỉ định loại(forall t. t->t) -> (Bool, Char)
chi

@chi Tôi quan tâm đến việc sử dụng , không phải định nghĩa, về các giá trị đa hình, xem phần chỉnh sửa của tôi để biết ví dụ về ý tôi muốn nói. Xin lỗi nếu điều này không rõ ràng lúc đầu.
jmite

Cần có một số bài báo của Simon Peyton-Jones giải thích thuật toán suy luận (mặc dù tôi không thể chỉ ra cái nào). Nhưng có lẽ các công cụ suy luận có thể thấy rằng gmong đợi một polytype, và ngăn chặn việc khởi tạo f.
chi

Câu trả lời:


7

Giới thiệu của bài báo Dunfield & Krishnaswami đề cập đến suy luận loại thực tế cho các loại xếp hạng tùy ý

Có thể thấy, nó có quy mô tốt cho các hệ thống loại tiên tiến; hơn nữa, nó rất dễ thực hiện và mang lại các thông báo lỗi chất lượng tương đối cao (Peyton Jones và cộng sự 2007)

Trong phương pháp hệ thống F-ish cũng có mối quan hệ "phân nhóm". Xem phần 3.3 Dự phòng.


Tôi cũng nhấn mạnh rằng Haskell không có các kiểu bắt buộc (hoặc suy luận cho chúng). Xem: https://mail.haskell.org/pipermail/ghc-devs/2016-September/012940.html để biết con trỏ.

  • Bạn có thể viết một polytype trong một đối số kiểu có thể nhìn thấy; ví dụ. f @ (tất cả a. a-> a)
  • Bạn có thể viết một polytype như một đối số của một loại trong chữ ký, ví dụ f :: [forall a. a-> a] -> Int

    Và đó là tất cả. Một biến thống nhất VẪN KHÔNG THỂ được thống nhất với một polytype. Cách duy nhất bạn có thể gọi một hàm đa hình ở đa giác là sử dụng Ứng dụng Kiểu hiển thị.

Nói tóm lại, nếu bạn gọi một hàm tại một polytype, bạn phải sử dụng VTA. Đơn giản, dễ dàng, có thể dự đoán được; và nghi ngờ khó chịu. Nhưng có thể.

Tức là id idsẽ luôn được xây dựng như

forall a. id @(a -> a) (id @a)

không phải

id @(forall a. a -> a) id

Tuy nhiên, bạn có thể viết cái sau một cách rõ ràng, nếu bạn bật ImpredicativeTypes.


3

Để kiểm tra việc áp dụng một chức năng như g : (forall a. a -> a) -> Intđể f, chúng ta cần phải kiểm tra xem f : forall a. a -> a.

Thay vì phù hợp với định lượng (đó sẽ là khá giòn), chúng tôi giới thiệu một tươi, cứng nhắc (tức là, không unifiable) biến, chẳng hạn a1, và chúng ta cần phải kiểm tra xem f : a1 -> a1, và bây giờ chúng ta có thể tiếp tục như thường lệ, instantiating ftại a1(modulo thêm kiểm tra để đảm bảo rằng a1không thoát khỏi phạm vi của nó).

Các thuật toán thực tế được chi tiết trong phadej giấy liên kết.

Hoặc, là đánh máy thậm chí có thể quyết định trong một hệ thống như vậy? Đây có phải là trường hợp mà ngôn ngữ như Haskell thực hiện một cái gì đó không thể giải quyết được sẽ xảy ra với hầu hết các trường hợp sử dụng của mọi người.

Vấn đề chung về suy luận kiểu trong sự hiện diện của đa hình xếp hạng cao hơn vẫn không thể giải quyết được. Tuy nhiên, với các chú thích kiểu đầy đủ, nó trở thành một vấn đề kiểm tra loại có thể quyết định (chủ yếu?) . Do đó, thuật toán của GHC phải không đầy đủ, nhưng cố gắng bao quát hết mức có thể ở giữa hai tình huống này, với sự trợ giúp của một vài chú thích loại thưa thớt.

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.