2014-10-29 32 views
8

Xin lỗi, tôi không thể tưởng tượng ra bất kỳ tiêu đề nào tốt hơn cho câu hỏi, vì vậy hãy đọc trước. Hãy tưởng tượng rằng chúng tôi có một gia đình kiểu khép kín mà các bản đồ tất cả các loại để nó tương ứng Maybe trừ maybes mình:Loại gia đình và loại chức năng lạ

type family Family x where 
    Family (Maybe x) = Maybe x 
    Family x = Maybe x 

Chúng tôi thậm chí có thể khai báo một hàm sử dụng loại gia đình:

doMagic :: a -> Family a 
doMagic = undefined 

exampleA = doMagic $ Just() 
exampleB = doMagic $() 

Chơi với nó trong GHCi cho thấy rằng nó là ok để đánh giá loại ứng dụng chức năng này:

*Strange> :t exampleA  
exampleA :: Maybe()  
*Strange> :t exampleB  
exampleB :: Maybe()  

câu hỏi đặt ra là nếu nó có thể cung cấp bất kỳ TRIỂN KHAI trên chức năng doMagic trừ undefined? Ví dụ, giả sử rằng tôi muốn bọc mọi giá trị vào một hàm tạo Just, ngoại trừ Maybes vẫn còn nguyên vẹn, làm cách nào tôi có thể làm điều đó? Tôi đã thử sử dụng typeclasses, nhưng không viết được chữ ký compileable cho chức năng doMagic nếu không sử dụng các loại gia đình khép kín, ai đó có thể giúp tôi được không?

+1

Trong ngôn ngữ được nhập động 'doMagic x = Just undefined' cũng sẽ tôn trọng các loại. Về mặt lý thuyết, một hệ thống kiểu có thể cho phép điều này (nhưng điều đó có thực sự hữu ích không?). BTW, ví dụ bạn mô tả, nếu bạn làm những thứ khác nhau tùy thuộc vào loại bê tông 'a' là, sẽ yêu cầu thông tin kiểu khi chạy, trong khi Haskell được thiết kế để cho phép xóa kiểu (không có thông tin kiểu khi chạy). Bạn có thể nhận được một cái gì đó gần bằng cách sử dụng một lớp loại, mặc dù. – chi

+1

Hơn nữa, câu hỏi có vẻ liên quan đến "định lý _ miễn phí của một loại trong sự hiện diện của các họ loại khép kín là gì?". – chi

Trả lời

8

Bạn có thể sử dụng một loại gia đình đóng khác để phân biệt Maybe x từ x và sau đó bạn có thể sử dụng một kiểu chữ khác để cung cấp triển khai riêng lẻ doMagic cho hai trường hợp này.Phiên bản nhanh và bẩn:

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, 
    FlexibleInstances, UndecidableInstances, ScopedTypeVariables #-} 

type family Family x where 
    Family (Maybe x) = Maybe x 
    Family x = Maybe x 

data True 
data False 

type family IsMaybe x where 
    IsMaybe (Maybe x) = True 
    IsMaybe x = False 


class DoMagic a where 
    doMagic :: a -> Family a 

instance (DoMagic' (IsMaybe a) a (Family a)) => DoMagic a where 
    doMagic = doMagic' (undefined :: IsMaybe a) 


class DoMagic' i a r where 
    doMagic' :: i -> a -> r 

instance DoMagic' True (Maybe a) (Maybe a) where 
    doMagic' _ = id 

instance DoMagic' False a (Maybe a) where 
    doMagic' _ = Just 


exampleA = doMagic $ Just() 
exampleB = doMagic $() 
+0

Điều đó thật tuyệt vời. – dfeuer

4

Bạn có thể thực hiện chức năng doMagic. Thật không may, đóng cửa của gia đình loại không thực sự giúp bạn nhiều. Đây là cách một sự khởi đầu có thể trông

{-# LANGUAGE TypeFamilies #-} 

type family Family x where 
    Family (Maybe x) = Maybe x 
    Family x = Maybe x 

class Magical a where doMagic :: a -> Family a 
instance Magical (Maybe a) where doMagic = id 
instance Magical() where doMagic = Just 

Bạn có thể nhìn thấy nó làm việc trong ghci cũng giống như bạn hỏi:

*Main> doMagic $ Just() 
Just() 
*Main> doMagic $() 
Just() 

Vậy tại sao tôi nói nó hobbling cùng? Vâng, bạn có thể nhận thấy rằng hai trường hợp cung cấp không bao gồm rất nhiều các hệ sinh thái Haskell các loại:

*Main> doMagic $ True 
<interactive>:3:1: 
    No instance for (Magical Bool) arising from a use of ‘doMagic’ 
    In the expression: doMagic 
    In the expression: doMagic $ True 
    In an equation for ‘it’: it = doMagic $ True 

Vì vậy, người ta sẽ phải cung cấp các trường hợp cho tất cả các loại (constructor) quan tâm. Thật vậy, ngay cả những trường hợp không mạch lạc - câu lạc bộ mà nhiều vấn đề như vậy có thể bị đánh bại khi đệ trình - giúp đỡ ở đây; nếu một người cố gắng viết

instance Magical (Maybe a) where doMagic = id 
instance Magical a where doMagic = Just 

trình biên dịch phải than phiền rằng sau tất cả chúng ta không biết rằng trường hợp đa hình thực sự có đúng loại. Điều về các trường hợp không mạch lạc là chúng ta không được trình biên dịch nói, chỉ vì đó là trường hợp được chọn, các trường hợp khác chắc chắn là không áp dụng. Vì vậy, có thể chúng ta chọn trường hợp đa hình hoàn toàn tại một số điểm, chỉ sau đó mới khám phá ra rằng chúng tôi thực sự là một hậu trường và sau đó chúng tôi chỉ quấn một lớp quá nhiều thứ Maybe xung quanh mọi thứ. Không may.

Hiện tại, không có nhiều việc có thể thực hiện được. Các loại gia đình khép kín tại thời điểm này không cung cấp tất cả những kiến ​​thức mà một người có thể muốn có sẵn. Có lẽ một ngày nào đó GHC sẽ cung cấp một cơ chế làm cho các gia đình đóng cửa hữu ích hơn trong vấn đề này như một ràng buộc bất bình đẳng, nhưng tôi sẽ không nín thở: đó là một vấn đề nghiên cứu cách cung cấp thông tin hữu ích này và tôi t nghe bất kỳ tin đồn của người giải quyết nó.

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