Các lớp học hơi lạ. Ý tưởng ban đầu (mà vẫn còn khá nhiều công trình) là một loại đường cú pháp xung quanh những gì nếu không sẽ là data
báo cáo. Ví dụ: bạn có thể tưởng tượng:
data Num a = Num {plus :: a -> a -> a, ... , fromInt :: Integer -> a}
numInteger :: Num Integer
numInteger = Num (+) ... id
thì bạn có thể viết các chức năng, ví dụ: loại:
test :: Num x -> x -> x -> x -> x
test lib a b c = a + b * (abs (c + b))
where (+) = plus lib
(*) = times lib
abs = absoluteValue lib
Vì vậy, ý tưởng là "chúng tôi sẽ tự động lấy được tất cả mã thư viện này". Câu hỏi đặt ra là, làm sao chúng ta tìm được thư viện mà chúng ta muốn? Thật dễ dàng nếu chúng ta có một thư viện kiểu Num Int
, nhưng làm thế nào để chúng tôi mở rộng nó thành "trường hợp bị hạn chế" dựa trên chức năng của loại:
fooLib :: Foo x -> Bar x
xyyLib :: Xyy x -> Bar x
Các giải pháp hiện tại trong Haskell là để làm một loại-Khuôn mẫu khớp với các kiểu đầu ra của các hàm đó và truyền các đầu vào cho khai báo kết quả. Nhưng khi có hai kết quả đầu ra của cùng loại, chúng ta sẽ cần một combinator mà kết hợp những thành:
eitherLib :: Either (Foo x) (Xyy x) -> Bar x
và về cơ bản vấn đề là không có tốt chế-combinator của loại hình này ngay bây giờ. Đó là phản đối của bạn.
Vâng, đó là sự thật, nhưng có nhiều cách để đạt được điều gì đó về mặt đạo đức tương tự trong thực tế. Giả sử chúng ta định nghĩa một số chức năng với các loại:
data F
data X
foobar'lib :: Foo x -> Bar' x F
xyybar'lib :: Xyy x -> Bar' x X
bar'barlib :: Bar' x y -> Bar x
rõ y
là một loại "loại ma" luồn qua tất cả những điều này, nhưng nó vẫn còn mạnh mẽ vì cho rằng chúng tôi muốn có một Bar x
chúng tôi sẽ tuyên truyền sự cần thiết của một Bar' x y
và cần có số điện thoại Bar' x y
, chúng tôi sẽ tạo ra Bar' x X
hoặc Bar' x y
. Vì vậy, với các loại phantom và các lớp kiểu đa tham số, chúng ta có được kết quả mà chúng ta muốn.
Thông tin khác: https://www.haskell.org/haskellwiki/GHC/AdvancedOverlap
Ví dụ GHC nên chọn nếu 'a' là' Foo' và 'Xyy'? – mb14
@ mb14: Tùy ý. ('IncoherentInstances' đã làm một cái gì đó tương tự, và tôi có thể sống với điều đó). – ron
Thật vậy, sự khác biệt duy nhất có vẻ là 'IncoherentInstances' cho phép GHC cam kết với một trong hai trường hợp, có thể loại bỏ một trường hợp có ngữ cảnh thỏa mãn và cam kết với một trường hợp không thỏa mãn (sẽ kích hoạt lỗi). Câu hỏi này thay vì hỏi tại sao GHC không có cờ 'BacktrackOnContextFailures', nếu tôi hiểu chính xác, để cho trường hợp chính xác cuối cùng được thử. Nó chắc chắn sẽ dẫn đến sự hấp dẫn trong những trường hợp xấu nhất, nhưng chúng ta đã có 'UndecidableInstances' có thể tác động đáng kể đến hiệu suất. – chi