2014-06-24 20 views
9

Nếu tôi có một loại bị hạn chế bởi một hữu hạn DataKindLấy thông tin từ DataKinds hạn chế loại hiện sinh

{-# LANGUAGE DataKinds #-} 

data K = A | B 

data Ty (a :: K) = Ty { ... } 

và một kiểu hiện sinh mà quên đi những lựa chọn chính xác của K trong các loại ... nhưng nhớ nó trong một trôi qua từ điển.

class AK (t :: K) where k :: Ty t -> K 
instance AK A where k _ = A 
instance AK B where k _ = B 

data ATy where ATy :: AK a => Ty a -> ATy 

nó thực sự là trường hợp mà ATy <-> Either (Ty A) (Ty B), nhưng nếu tôi muốn viết một trong những nhân chứng tôi cần phải sử dụng unsafeCoerce

getATy :: ATy -> Either (Ty A) (Ty B) 
getATy (ATy it) = case k it of 
    A -> Left (unsafeCoerce it) 
    B -> Right (unsafeCoerce it) 

Vì vậy, nhìn chung các công trình này, tôi có thể quên lựa chọn K sử dụng ATy và nhớ một phần sử dụng getATy. Tất cả điều này tận dụng lợi thế của nhiều thông tin kiểu như tôi có sẵn.

Tuy nhiên, thông tin loại này cảm thấy như thể nó phải là "hiển nhiên" nếu được thực hiện đúng.

Có cách nào để đạt được điều này mà không cần sử dụng unsafeCoerce không? Có cách nào để thoát khỏi ràng buộc AK trong sự tồn tại? Kỹ thuật này có thể được thực hiện hoàn toàn dựa trên các ràng buộc thông tin do kiểu dữ liệu cung cấp không?

+0

Ahm ... 'A -> Trái Ty'? – leftaroundabout

+0

Ah, uh, hãy để tôi thay đổi ví dụ để làm cho nó ít tầm thường hơn. Rất tiếc! –

+0

Loại 'K' có thể là ma, nhưng nó truyền tải rất nhiều thông tin. –

Trả lời

9

Nếu bạn muốn làm phân tích trường hợp thời gian chạy vào loại hiện sinh, bạn cần một đại diện singleton quá:

{-# LANGUAGE DataKinds, GADTs, KindSignatures, ScopedTypeVariables #-} 

data K = A | B 

-- runtime version of K. 
data SK (k :: K) where 
    SA :: SK A 
    SB :: SK B 

-- ScopedTypeVariables makes it easy to specify which "k" we want. 
class AK (k :: K) where 
    k :: SK k 

instance AK A where k = SA 
instance AK B where k = SB 

data Ty (a :: K) = Ty 

data ATy where 
    ATy :: AK k => Ty k -> ATy 

getATy :: ATy -> Either (Ty A) (Ty B) 
getATy (ATy (ty :: Ty k)) = case (k :: SK k) of 
    SA -> Left ty 
    SB -> Right ty 

Gói singletons có thể được sử dụng ở đây để làm đi với các soạn sẵn:

{-# LANGUAGE DataKinds, GADTs, TypeFamilies, TemplateHaskell, ScopedTypeVariables #-} 

import Data.Singletons.TH 

$(singletons [d| data K = A | B |]) 

data Ty (a :: K) = Ty 

data ATy where 
    ATy :: SingI k => Ty k -> ATy 

getATy :: ATy -> Either (Ty A) (Ty B) 
getATy (ATy (ty :: Ty k)) = case (sing :: Sing k) of 
    SA -> Left ty 
    SB -> Right ty 

Đối với câu hỏi cuối cùng của bạn:

Có cách nào để loại bỏ ràng buộc AK đó không trong sự tồn tại? Kỹ thuật này có thể được thực hiện hoàn toàn dựa trên thông tin ràng buộc do kiểu dữ liệu cung cấp không?

Miễn là chúng tôi chỉ có loại dữ liệu làm thông số loại, thông tin không tồn tại trong thời gian chạy và chúng tôi không thể phân tích về nó. Ví dụ: lấy loại này:

data ATy where 
    ATy :: Ty k -> ATy 

chúng tôi không bao giờ có thể nhanh chóng k trong Ty k; nó phải vẫn còn đa hình.

Có nhiều cách để cung cấp thông tin loại thời gian chạy; ngầm thông qua các từ điển là một lựa chọn, như chúng ta đã nhìn thấy:

data ATy where 
    ATy :: AK k => Ty k -> ATy 

đây AK k chỉ là một con trỏ đến một SK (từ lớp AK chỉ có một phương pháp duy nhất, chúng ta không có một từ điển cho lớp , chỉ cần một con trỏ đơn giản đến phương thức), một trường bổ sung trong hàm tạo.Chúng tôi cũng có thể chọn để làm cho trường đó rõ ràng:

data ATy where 
    ATy :: SK k -> Ty k -> ATy 

và trình bày thời gian chạy sẽ khá giống nhau.

Một lựa chọn thứ ba sẽ được sử dụng nhà xây dựng GADT để mã hóa các loại:

data ATy where 
    ATyA :: Ty A -> ATy 
    ATyB :: Ty B -> ATy 

Giải pháp này là hiệu suất khá đẹp khôn ngoan, vì không có không gian trên cao, như các nhà thầu đã mã hóa các loại. Nó giống như một số Either với thông số loại ẩn.

+0

Ah, vì vậy GADT đơn mang theo sự bình đẳng loại chúng ta cần. Đó là phần tôi đã mất tích –

+0

@ J.Abrahamson Tôi đã thêm một số ghi chú về các biểu diễn loại thay thế. –

+0

Tuyệt vời, cảm ơn thông tin. Đây chính xác là những gì tôi đã mất tích. –

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