2016-11-23 14 views
8

Tôi có ví dụ này tối thiểu làm việc (chọn lọc từ thư viện singletons) của ánh xạ một gia đình kiểu trên một danh sách loại cấp:Tại sao mã này không vi phạm "yêu cầu bão hòa của các họ loại"?

{-# language PolyKinds #-} 
{-# language DataKinds #-} 
{-# language TypeFamilies #-} 
{-# language TypeOperators #-} 

data TyFun :: * -> * -> * 

data TyCon1 :: (k1 -> k2) -> (TyFun k1 k2 -> *) 

type family Apply (f :: TyFun k1 k2 -> *) (x :: k1) :: k2 
type instance Apply (TyCon1 f) x = f x 

type family Map (f :: TyFun a b -> *) (as :: [a]) :: [b] where 
    Map f '[] = '[] 
    Map f (x ': xs) = Apply f x ': Map f xs 

type family Flip t :: * where 
    Flip Int = Char 
    Flip Char = Int  

Có vẻ như để làm việc:

ghci> :set -XDataKinds 
ghci> :kind! Map (TyCon1 Flip) '[Char,Int] 
Map (TyCon1 Flip) '[Char,Int] :: [*] 
= '[Int, Char] 

Mã này được giải thích trong bài đăng Defunctionalization for the win. Đó là một giải pháp cho thực tế là "GHC sẽ không cho phép một biến kiểu hợp nhất với một họ loại". Điều này được gọi là "yêu cầu bão hòa của các loại gia đình".

Nghi ngờ của tôi là: khi chúng tôi "chạy" :kind! Map (TyCon1 Flip) '[Char,Int] có vẻ như, trong dòng type instance Apply (TyCon1 f) x = f x, f sẽ được khớp với gia đình loại Flip của chúng tôi. Tại sao điều này không vi phạm yêu cầu bão hòa?

+0

Tôi không nghĩ rằng đó là nghĩa vụ phải làm việc. Tuy nhiên, nó hoàn toàn vô hại vì các từ đồng nghĩa được mở rộng trong việc kiểm tra kiểu. – dfeuer

+1

Tôi tin rằng bạn thực sự được yêu cầu cung cấp một biểu tượng khử chức năng cho 'Flip' với cá thể' Áp dụng' của chính nó. 'TyCon1' được thiết kế để áp dụng cho các nhà xây dựng kiểu. Nhân tiện, phiên bản GHC này là gì? – dfeuer

+1

@dfeuer Tôi đang sử dụng GHC 8.0.1. Rõ ràng, điều này hoạt động khi sử dụng ': kind! 'Trong ghci, nhưng nếu tôi cố gắng thêm một cái gì đó như' gõ Boo = Map (TyCon1 Flip)' [Char, Int] 'vào tập lệnh, nó cho tôi một lỗi biên dịch. – danidiaz

Trả lời

2

Tôi đang trả lời câu hỏi của riêng mình với thông tin được chọn lọc từ nhận xét của người gửi và nhận xét của người dùng2407038.

Hóa ra mã của tôi đã làm vi phạm yêu cầu bão hòa. Tôi không tìm thấy lỗi vì một hành vi lạ (lỗi?) Của :kind! trong ghci. Nhưng hãy viết loại trong chính tệp hs cho lỗi biên dịch.

TyCon1 không dành cho các họ loại, nhưng đối với việc đóng gói các nhà xây dựng kiểu thông thường như Maybe, không có vấn đề gì hợp nhất với các biến kiểu. Ví dụ: type Foo = Map (TyCon1 Maybe) '[Char,Int] hoạt động tốt.

Đối với các họ loại, chúng tôi cần xác định loại phụ trợ đặc biệt cho từng loại, sau đó xác định một thể hiện Apply cho loại. Như thế này:

data FlipSym :: TyFun * * -> * 
type instance Apply FlipSym x = Flip x 

type Boo = Map FlipSym '[Char,Int] 

Lưu ý rằng cách này loại gia đình Flip không thống nhất với bất kỳ loại biến nào.

+1

Xin lỗi tôi đã không nhận được xung quanh để đưa lên một câu trả lời bản thân mình. Của bạn ít nhất là tốt như những gì tôi đã viết. Một nit tôi muốn chọn: Tôi không thích cái tên «Flip' cho gia đình đó. Trong tâm trí của tôi, tên đó luôn được định nghĩa 'newtype Flip (f :: j -> k -> *) (y :: k) (x :: j) = Lật {unFlip :: f x y}'.Phiên bản cấp loại kết quả của 'lật' xuất hiện khá thường xuyên, và nói chung trong các ngữ cảnh trong đó phiên bản loại đồng nghĩa (' loại Flip f y x = f x y') sẽ không hữu ích. – dfeuer

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