Đa hình Levity là gì


80

Như tiêu đề của câu hỏi đã chỉ ra, tôi muốn biết đa hình Levity là gì và động lực của nó là gì? Tôi biết trang này có một số chi tiết trong đó, nhưng hầu hết các giải thích ở đó đều vượt qua đỉnh đầu của tôi. :)

Mặc dù trang này thân thiện hơn một chút, nhưng tôi vẫn không thể hiểu động lực đằng sau nó.

Câu trả lời:


80

Lưu ý: Câu trả lời này dựa trên những quan sát gần đây về các cuộc thảo luận về Levity. Mọi thứ liên quan đến tính đa hình Levity hiện chỉ được triển khai trong các ứng cử viên phát hành GHC 8.0 và có thể thay đổi ( ví dụ: xem # 11471 ).


TL; DR : Đó là một cách để tạo ra các hàm đa hình trên các loại nâng và không có hàm, điều này không thể thực hiện được với các hàm thông thường. Ví dụ: mã sau đây không kiểm tra kiểu với các đa hình thông thường, vì Int#có loại #, nhưng các biến loại trong idcó loại *:

{-# LANGUAGE MagicHash #-}

import GHC.Prim

example :: Int# -> Int# 
example = id            -- does not work, since id :: a -> a
Couldn't match kind ‘*’ with ‘#’
When matching types
  a0 :: *
  Int# :: #
Expected type: Int# -> Int#
  Actual type: a0 -> a0
In the expression: id

Lưu ý rằng (->)vẫn sử dụng một số phép thuật.


Trước khi tôi bắt đầu trả lời câu hỏi này, chúng ta hãy lùi lại một bước và chuyển đến một trong những hàm thường được sử dụng nhất ($),.

Là gì ($)'s loại? Vâng, theo Hackage và báo cáo, nó

($) :: (a -> b) -> a -> b

Tuy nhiên, điều đó không hoàn toàn 100%. Đó là một lời nói dối nhỏ tiện lợi. Vấn đề là loại đa hình (giống ab) có loại *. Tuy nhiên, các nhà phát triển (thư viện) ($)không chỉ muốn sử dụng cho các loại với loại *, mà còn cho loại loại #, ví dụ:

unwrapInt :: Int -> Int#

Trong khi Intcó tử tế *(nó có thể là đáy), Int#có tử tế #(và không thể ở dưới cùng). Tuy nhiên, các kiểu gõ mã sau:

unwrapInt $ 42

Điều đó sẽ không hoạt động. Hãy nhớ loại trả lại của ($)? Đó là loại đa hình, và các loại đa hình có loại *, không #! Vậy tại sao nó hoạt động? Đầu tiên, đó là một lỗi , sau đó là một vụ hack (trích đoạn thư của Ryan Scott trong danh sách gửi thư ghc-dev):

Vậy tại sao điều này xảy ra?

Câu trả lời dài là trước GHC 8.0, trong chữ ký kiểu ($) :: (a -> b) -> a -> b, bthực sự không phải bằng hiện vật *, mà là OpenKind. OpenKindlà một cuộc tấn công khủng khiếp cho phép cả loại nâng cao (tử tế *) và không có kỹ năng (loại #) sống trong nó, đó là lý do tại sao đánh máy (unwrapInt $ 42) .

Vậy ($)loại mới trong GHC 8.0 là gì? nó là

($) :: forall (w :: Levity) a (b :: TYPE w). (a -> b) -> a -> b
-- will likely change according to Richard E.

Để hiểu nó, chúng ta phải xem Levity:

data Levity = Lifted | Unlifted

Bây giờ, chúng ta có thể ($)coi là có một trong hai loại sau, vì chỉ có hai lựa chọn w:

-- pseudo types
($) :: forall a (b :: TYPE   Lifted). (a -> b) -> a -> b
($) :: forall a (b :: TYPE Unlifted). (a -> b) -> a -> b

TYPElà một hằng số ma thuật và nó xác định lại các loại *#như

type * = TYPE Lifted
type # = TYPE Unlifted

Việc định lượng các loại cũng khá mới và là một phần của việc tích hợp các loại phụ thuộc trong Haskell .

Tên đa hình Levity xuất phát từ thực tế là giờ đây bạn có thể viết các hàm đa hình trên cả kiểu nâng và không ghép, một điều không được phép / có thể thực hiện được với các hạn chế về đa hình trước đây. Nó cũng đồng thời loại bỏ OpenKindhack. Nó thực sự "chỉ" về điều này, xử lý cả hai loại.

Nhân tiện, bạn không đơn độc với câu hỏi của mình. Ngay cả Simon Peyton Jones cũng nói rằng cần phải có một trang wiki Levity , và Richard E. (người thực hiện điều này hiện tại) đã nói rằng trang wiki cần cập nhật quy trình hiện tại.

Người giới thiệu


3
"xử lý cả hai loại" :)
Sibi

4
Huh. Tôi nghĩ rằng tôi thích một vụ hack xấu xí đã giấu nội dung này.
jberryman 10/02/16

3
Tại sao nó không ($) :: forall (w1 w2 :: Levity) (a :: TYPE w1) (b :: TYPE w2). (a -> b) -> a -> b, tức là tại sao ($)không được cho là có thể sử dụng được với các hàm có đối số không có biên?
Cactus

3
@Cactus được thảo luận trong "lỗi", hãy xem nhận xét này của SPJ: ghc.haskell.org/trac/ghc/ticket/8739#comment:6
Zeta

1
@jberryman: # 11549 sẽ ẩn RuntimeRep(thay thế Levity).
Zeta
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.