2016-12-10 12 views
8

Tôi đã gặp một tình huống kỳ lạ trong GHC 8.0.1 với GADT được đánh chỉ mục (?), Nơi giới thiệu yếm trong loại so với chữ ký loại. hành vi.'Loại' bị nhầm lẫn về forall trong GADT được đánh số loại

Hãy xem xét các kiểu dữ liệu sau:

{-# LANGUAGE TypeInType, GADTs, ExplicitForAll #-} 
-- Same thing happens when we replace ExplicitForAll with ScopedTypeVariables 

import Data.Kind 

data F (k :: * -> *) where 

data G :: F k -> * where 
    G :: G x 

kiểu dữ liệu này biên dịch tốt. Tuy nhiên, nếu chúng ta muốn chỉ định loại x trong hàm tạo G, chúng tôi sẽ gặp lỗi kiểu.

data H :: F k -> * where 
    H :: forall k' (x :: F k'). H x 

Các thông báo lỗi là

• Kind variable ‘k’ is implicitly bound in datatype 
    ‘H’, but does not appear as the kind of any 
    of its type variables. Perhaps you meant 
    to bind it (with TypeInType) explicitly somewhere? 
• In the data declaration for ‘H’ 

Nếu chúng ta thêm forall để chữ ký kiểu (có hoặc không có forall trong constructor), không có lỗi.

data I :: forall k. F k -> * where 
    I :: I x 

data J :: forall k. F k -> * where 
    J :: forall k' (x :: F k'). J x 

Điều gì đang xảy ra?

+6

chơi chữ thật sự tuyệt vời. A + – rampion

+0

Có vẻ như trước đây khai báo 'F k' được sửa cho toàn bộ khai báo, trong khi cái sau cho phép' H' được sử dụng trong khai báo riêng của nó ở các loại khác nhau. I E. nó cho phép đệ quy polykinded. Có thể tương tự như sự khác biệt "thông số so với chỉ số" trong các loại quy nạp (như trong Agda/Coq). – chi

+3

Dường như đây có thể là lỗi trình biên dịch (vừa được sửa). Tôi có thể sao chép thông báo lỗi của bạn bằng "ghc-8.0.1" nhưng nó biên dịch tốt với "ghc-8.0.1.20161117", phiên bản mới nhất "ngăn xếp" đã quyết định cài đặt cho tôi (và đó dường như là một ứng cử viên phát hành cho 8.0 .2). –

Trả lời

3

Tác giả của TypeInType tại đây. K. A. Buhr nhận được nó ngay trên; đây chỉ là một lỗi. Nó được cố định trong HEAD.

Đối với quá tò mò: thông báo lỗi này có nghĩa là để loại bỏ các định nghĩa như

data J = forall (a :: k). MkJ (Proxy a) 

nơi

data Proxy (a :: k) = Proxy 

có thể được nhập khẩu từ Data.Proxy. Khi khai báo một kiểu dữ liệu trong cú pháp kiểu Haskell98, bất kỳ biến định lượng hiện có nào phải được đưa vào phạm vi một cách rõ ràng với một forall. Nhưng k không bao giờ được đưa vào phạm vi một cách rõ ràng; nó chỉ được sử dụng trong các loại a. Vì vậy, điều đó có nghĩa là k nên được định lượng phổ biến (nói cách khác, nó phải là một tham số vô hình cho J, như tham số k đến Proxy) ... nhưng khi chúng tôi viết J, không có cách nào để xác định xem k , vì vậy nó sẽ luôn mơ hồ. (Ngược lại, chúng ta có thể khám phá các lựa chọn tham số k để Proxy bằng cách nhìn vào loại a 's.)

Định nghĩa này cho J là không được phép trong 8.0.1 và trong HEAD.

Các vấn đề liên quan