Được rồi, đây là một góc ma quái kỳ lạ của hệ thống kiểu Haskell. Vấn đề ở đây là có hai cách để suy luận chức năng của bạn foo
.
-- rank 1
foo :: forall a b. (a -> b) -> a -> a -> (b, b)
foo f a b = (f a, f b)
-- rank 2
foo' :: (forall a. a -> a) -> a -> b -> (a, b)
foo' f a b = (f a, f b)
Loại thứ hai là loại bạn muốn, nhưng loại thứ nhất là loại bạn muốn. Loại thứ hai, như amalloy đã chỉ ra, là một loại hạng 2 (chúng ta sẽ bỏ qua ý nghĩa của hai phương pháp này nhưng đọc phần giới thiệu trong "Practical type inference for arbitrary-rank types" nếu bạn muốn giải thích tốt về các cấp bậc - không được đưa ra bởi bản chất của tập tin PDF khi bắt đầu được viết rõ ràng và rõ ràng).
Chúng tôi sẽ hoãn định nghĩa các loại xếp hạng cao hơn hiện tại và chỉ nói rằng vấn đề là GHC không thể suy ra loại xếp hạng 2. Trích dẫn bài báo:
Complete type inference is known to be undecidable for higher-rank (impredicative) type systems, but in practice programmers are more than willing to add type annotations to guide the type inference engine, and to document their code....
Kfoury and Wells show that typeability is decidable for rank ≤ 2, and undecidable for all ranks ≥ 3 (Kfoury & Wells, 1994). For the rank-2 fragment, the same paper gives a type inference algorithm. This inference algorithm is somewhat subtle, does not interact well with user-supplied type annotations, and has not, to our knowledge, been implemented in a production compiler.
Có nghĩa là không thể có thuật toán luôn dẫn đến quyết định có hoặc không chính xác. Vì vậy, có bạn có nó: không thể suy ra một loại cấp bậc 3 hoặc cao hơn, và nó quá gosh-darn-khó để suy ra loại hạng 2.
Bây giờ, quay lại xếp hạng 2. (forall a. a -> a)
là thứ giúp xếp hạng 2. There's already an excellent Stack Overflow question about what the forall
keyword means vì vậy tôi sẽ giới thiệu bạn đến đó, nhưng về cơ bản nó có nghĩa là bạn có thể gọi f a
và f b
trong biểu thức (f a, f b)
khi có a
và b
thể loại khác nhau, đó là những gì bạn muốn ở nơi đầu tiên, trước khi tất cả mớ hỗn độn nóng bỏng này.
Điều cuối cùng: Lý do bạn thường không thấy forall
s trong GHCi là bất kỳ forall
giây nào trên phạm vi ngoài cùng đều bị tắt. Vì vậy, forall a b. (a -> b) -> a -> a -> (b, b)
tương đương với (a -> b) -> a -> a -> (b, b)
.
Nhìn chung đây là điểm đau của ngôn ngữ được giải thích kém.
(Hat tip để @amalloy trong các ý kiến.)
là http://stackoverflow.com/questions/32496864/what-is-the-monomorphism-restriction những gì bạn muốn? – hao
@haoformayor Không, đây là về 'forall', không phải là hạn chế đơn hình, tôi nghĩ vậy. Kiểu suy ra cho 'foo' sẽ phải là' (forall a. A -> a) -> a -> b -> (a, b) ', nhưng AFAIK haskell không bao giờ thâm nhập các kiểu với' forall' (được gọi là rank -2 loại, tôi nghĩ vậy?), ngay cả khi hạn chế monomorphism bị vô hiệu hóa. – amalloy
ah, đó là câu trả lời. ghc đưa vào loại rank-1 'forall a b. (a -> b) -> a -> a -> (b, b) ', nhưng bạn thực sự muốn' (forall a. a -> a) -> a -> b -> (a, b) '. – hao