2012-04-12 25 views
8

Tôi không quá quen thuộc với forall, nhưng gần đây đọc câu hỏi này: What does the `forall` keyword in Haskell/GHC do?Tại sao không forall (RankNTypes sử dụng) áp dụng theo mặc định?

Trong một trong những câu trả lời là ví dụ này:

{-# LANGUAGE RankNTypes #-} 
liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b) 
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v) 

Câu trả lời rất tốt và tôi hiểu những gì forall đang làm gì ở đây. Nhưng tôi tự hỏi, có một lý do cụ thể tại sao đây không phải là hành vi mặc định. Có bao giờ một thời gian mà nó sẽ là bất lợi?

Chỉnh sửa: Ý tôi là, có lý do tại sao không thể chèn vào forall theo mặc định?

+3

Bạn có hỏi tại sao phần mở rộng không được bật theo mặc định hay không? -> (fa, fb) 'không được xử lý giống như' (forall x. x -> fx) -> (a, b) -> (fa, fb) '? Nếu đó là sau này, bạn có thể chỉ định logic mà bạn đề xuất trình biên dịch nên quyết định nơi để chèn 'forall's? – sepp2k

+0

Sau này, và tôi sẽ không biết bắt đầu đề xuất bất cứ điều gì ở tất cả về chủ đề này! –

+0

Lưu ý rằng kiểu '(x -> f x) -> (a, b) -> (f a, f b)' là khá vô ích. Hàm không thể áp dụng đối số đầu tiên cho một trong hai phần tử của bộ tuple, do đó kết quả của nó phải là '⊥' hoặc' (⊥, ⊥) '. – hammar

Trả lời

16

Vâng, nó không phải là một phần của tiêu chuẩn Haskell 2010, do đó, nó không được bật theo mặc định và được cung cấp dưới dạng tiện ích mở rộng ngôn ngữ thay thế. Đối với lý do tại sao nó không phải trong tiêu chuẩn, các loại rank-n là khá khó khăn hơn để thực hiện hơn so với các loại đồng bằng hạng 1 tiêu chuẩn Haskell có; họ cũng không cần tất cả những điều đó thường xuyên, vì vậy Ủy ban có thể quyết định không bận tâm với họ vì lý do ngôn ngữ và thực hiện đơn giản.

Tất nhiên, điều đó không có nghĩa là các loại hạng n không hữu ích; chúng có rất nhiều công cụ có giá trị như ST monad (trong đó cung cấp trạng thái có thể biến đổi cục bộ, hiệu quả như IO, nơi tất cả những gì bạn có thể làm là sử dụng IORef s). Nhưng chúng làm tăng thêm một chút phức tạp cho ngôn ngữ và có thể gây ra hành vi lạ khi áp dụng các phép biến đổi mã có vẻ lành tính. Ví dụ: một số trình kiểm tra loại xếp hạng n sẽ cho phép runST (do { ... }) nhưng từ chối runST $ do { ... }, mặc dù hai biểu thức luôn luôn tương đương mà không có loại xếp hạng n. Xem this SO question để biết ví dụ về hành vi bất ngờ (và đôi khi gây phiền nhiễu) có thể gây ra.

Nếu, như sepp2k hỏi, bạn thay vì hỏi tại sao forall phải được thêm một cách rõ ràng vào chữ ký để tăng tổng quát, vấn đề là (forall x. x -> f x) -> (a, b) -> (f a, f b) thực sự là loại hạn chế hơn (x -> f x) -> (a, b) -> (f a, f b). Sau đó, bạn có thể chuyển vào bất kỳ chức năng nào của biểu mẫu x -> f x (đối với bất kỳ fx) nào, nhưng với chức năng cũ, chức năng bạn chuyển vào phải hoạt động cho tất cảx. Vì vậy, ví dụ, một chức năng của loại String -> IO String sẽ là một đối số cho phép để chức năng thứ hai, nhưng không phải là đầu tiên; nó phải có kiểu a -> IO a thay thế. Nó sẽ khá là khó hiểu nếu sau này được tự động biến thành cái cũ! Chúng là hai loại rất khác nhau.

Nó có thể có ý nghĩa hơn với những tiềm ẩn forall s làm rõ:

forall f x a b. (x -> f x)   -> (a, b) -> (f a, f b) 
forall f a b. (forall x. x -> f x) -> (a, b) -> (f a, f b) 
+0

Tôi nghĩ rằng tôi cần phải tiêu hóa điều này một số chi tiết :) –

+0

Ngoài ra, đối với đa hình bậc hai và cao hơn, không có thứ gì như kiểu chung nhất, '∀ b. (∀ a. A → b) → (b, b) 'không tổng quát hơn' ∀ c d. (∀ a. A → b) → (c, d) 'cũng không phải cách khác. Và trong khi suy luận kiểu là decidable cho đa hình thứ nhất và thứ hai, nó không phải là thứ ba và cao hơn. – Vitus

+0

@vitus - bạn có thể cung cấp một tham chiếu về tính quyết định của đa hình bậc hai không? Tôi không quen với nó. –

7

tôi nghi ngờ rằng các loại cấp bậc cao hơn không được kích hoạt theo mặc định vì they make type inference undecidable. Đây cũng là lý do tại sao, ngay cả khi tiện ích mở rộng được bật, bạn cần sử dụng từ khóa forall để có loại xếp hạng cao hơn - GHC giả định rằng tất cả các loại đều xếp hạng 1 trừ khi được nói cách khác để suy ra nhiều thông tin nhất có thể.

Nói cách khác, không có cách nào nói chung để suy ra một loại hạng cao (forall x. x -> f x) -> (a,b) -> (f a, f b), vì vậy cách duy nhất để có được kiểu đó là do một loại chữ ký rõ ràng.

Chỉnh sửa: mỗi nhận xét của Vitus ở trên, suy luận loại bậc 2 là đáng tin cậy, nhưng đa hình bậc cao thì không. Vì vậy, chữ ký kiểu này là không thể thay đổi về mặt kỹ thuật (mặc dù thuật toán phức tạp hơn).Cho dù sự phức tạp thêm của việc cho phép suy luận kiểu đa hình bậc 2 có đáng tranh cãi hay không ...

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