2015-02-13 16 views
6

xem xét mã Haskell sau:Haskell phụ thuộc chức năng a b -> c tùy thuộc vào c?

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, 
    FunctionalDependencies #-} 

class C a b c | a b -> c 

instance C (l (i,j)) (r i j) j 
instance C (l i j) (r (i,j)) j 
-- Conflict between the following two lines 
instance C (l (i,j)) (r (i,j)) j 
instance C (l i j) (r i j) j 

Ở đây, GHC mang lại một lỗi phụ thuộc hàm giữa hai dòng cuối cùng. Nếu tôi thả bất kỳ một trong hai khai báo cá thể cuối cùng, thì mã sẽ biên dịch. Tôi đã thử một loại gia đình tương tự bằng cách sử dụng, mà cũng tạo ra một cuộc xung đột. Câu hỏi đầu tiên của tôi là: Tại sao hai dòng cuối cùng xung đột, trong khi các tờ khai khác tất cả đều làm việc tốt với nhau?

Bên cạnh đó, nếu tôi thay đổi dòng cuối cùng để

instance C (l i j) (r i j) i 

GHC chấp nhận mã. Điều này có vẻ hơi lạ, vì điều duy nhất thay đổi là biến loại phụ thuộc c. Ai đó có thể giải thích hành vi này?

+0

Chỉ để đảm bảo. Nếu bạn xóa cả hai phiên bản đầu tiên thì vẫn có lỗi, phải không? – genisage

+0

@genisage Vâng, nó chỉ phụ thuộc vào hai trường hợp cuối cùng –

+0

Tôi không thể tái tạo phần thứ hai ở đây. 'instance C (l i j) (r i j) i' gây ra xung đột cho tôi. (trên ghc 7.8.3) – genisage

Trả lời

6

Hai trường hợp cuối cùng có thống nhất xung đột. Hãy để tôi sử dụng tên biến hoàn toàn khác nhau:

C (a c (d,e)) (b c (d,e)) e 
vs. 
C (a c (d,e)) (b c (d,e)) (d,e) 

Đặc biệt, l của bạn từ Ví dụ thứ ba có thể được thống nhất với một constructor loại mà đã có một cuộc tranh cãi áp dụng.

Thay đổi j-i của bạn làm cho người cuối cùng thay vì:

C (a c (d,e)) (b c (d,e)) c 

tôi vẫn không hiểu tại sao mà không đưa ra một lời phàn nàn. Có lẽ vì bạn có thể gán các loại như vậy c = e, nhưng không phải như vậy mà e = (d,e) (có thể cung cấp loại vô hạn mà Haskell không cho phép), nhưng nó vẫn có vẻ như một thứ không rõ ràng để cho phép. Có lẽ đây thậm chí là lỗi của GHC.

Các kết hợp thể hiện khác không xung đột vì khi bạn cố gắng hợp nhất chúng, bạn kết thúc với mâu thuẫn tương tự như e = (d,e) ở trên, nhưng trong các phần không phụ thuộc, vì vậy chúng không thể khớp.

+0

Tôi đồng ý với bạn. Thử nghiệm, tôi thấy rằng 'lớp C a b; cá thể C (l (i, j)) (r (i, j)); Ví dụ C (l i j) (r i j) 'là _accepted_ mà không nhắc đến sự chồng chéo (!?). Có lẽ bây giờ một số chồng chéo đang được phát hiện chỉ sau đó, khi một phương pháp được gọi là (chỉ đoán ở đây). – chi

+0

Cảm ơn bạn đã chỉ ra quy trình thống nhất. @chi: Thật vậy, nếu tôi cố gắng viết một phương thức lớp 'f :: a -> b -> c' tôi nhận được một khiếu nại abount sự không mạch lạc khi gọi' f' –

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