2010-05-21 31 views
16

Nghe có vẻ ngớ ngẩn, nhưng tôi không hiểu. Tại sao biểu thức [] == [] lại được gõ? Cụ thể hơn, loại nào (trong lớp Eq) được suy ra cho loại phần tử danh sách?Làm thế nào là loại `([] ==) []` haskell suy luận?

Trong một phiên ghci, tôi thấy như sau:

Prelude> :t (==[]) 
(==[]) :: (Eq [a]) => [a] -> Bool 

Nhưng hạn chế Eq [a] ngụ ý Eq a cũng có, như được hiển thị ở đây:

Prelude> (==[]) ([]::[IO()]) 

<interactive>:1:1: 
No instance for (Eq (IO())) 
    arising from use of `==' at <interactive>:1:1-2 
Probable fix: add an instance declaration for (Eq (IO())) 
In the definition of `it': it = (== []) ([] :: [IO()]) 

Như vậy, trong [] == [] , trình kiểm tra kiểu phải giả định rằng phần tử danh sách là một kiểu nào đó có trong lớp Eq. Nhưng cái nào? Kiểu [] chỉ là [a], và điều này chắc chắn là tổng quát hơn Eq a => [a].

IMHO này nên bởi mơ hồ, ít nhất là trong Haskell 98 (đó là những gì chúng ta đang nói về)

+3

Với GHC (không GHCi) Tôi đã có 'Biến loại mơ hồ \' a 'trong ràng buộc \ 'Eq a 'phát sinh từ việc sử dụng \' ==' ' – kennytm

+0

@Kenny - có thats những gì tôi mong đợi trước khi tôi thử trong ghci - sự ngạc nhiên của tôi càng lớn. Cảm ơn gợi ý, bây giờ trật tự thế giới của tôi được khôi phục :) – Ingo

+0

Đó là những cái ôm thú vị cho biểu thức '[] == []' loại 'Eq a => Bool'. – sdcvvc

Trả lời

19

GHCi có extended rules for type defaulting, đó là những gì bạn đã mắc phải. Trong trường hợp này, tôi tin rằng nó sẽ mặc định kiểu mơ hồ thành (). Những cách tinh tế mà GHCi cư xử khác nhau là tốt đẹp vì lợi ích của tương tác tốt hơn, nhưng đôi khi chúng dẫn đến sự nhầm lẫn ...

+8

@camccann: chạy 'ghci -Wall'. sau đó '[] == []' nhận 'Cảnh báo: Mặc định (các) ràng buộc sau đây để gõ '()'' – yairchu

+1

Việc mặc định mở rộng chỉ có vấn đề khi bạn muốn hiển thị hoặc chạy mã. Các :: (Eq a) => [a] -> Bool loại là hoàn toàn chính xác. –

+1

@Don Stewart: Loại đó là tất nhiên là tốt - tôi nghĩ rằng Ingo nhầm lẫn là '([] == []) :: Bool', nơi ràng buộc' Eq a' mơ hồ được thỏa mãn bằng cách mặc định thành '() ', như yairchu đã chứng minh. –

1

GHC suy luận kiểu chung nhất:

(== []) :: (eq a) => [a] -> Bool

Nó cần được đọc như sau:

  • nếu bạn có một thể hiện của eq một,
  • sau đó Haskell có thể cung cấp cho bạn một chức năng từ danh sách của những 'một là để bool

Vì vậy, có, ngụ ý ở đây là bạn có một thể hiện của phương trình cho các yếu tố của danh sách, và GHC đã có một ví dụ cho các danh sách nói chung (dựa vào phương trình cho các phần tử), vì vậy chúng tôi có được một loại chung tốt đẹp.

Trình kiểm tra loại "giả định" bạn có thể cung cấp một Eq một thể hiện khi được gọi ở một loại cụ thể.

Tôi không thể sao chép kết quả của bạn có ràng buộc Eq [a].

+0

mặc dù Kenny ở trên có kết quả khác với GHC. Lưu ý: Chúng tôi đang nói haskell 98, tôi chắc chắn một số phần mở rộng GHC ưa thích là đủ thông minh để gõ nó một cách chính xác, nhưng tôi vẫn không hiểu chính xác như thế nào. IMHO, đây thực sự là một trường hợp mơ hồ. – Ingo

+1

@Ingo: '(== [])' không rõ ràng, chỉ đa hình như bình thường; nó sẽ làm việc giống nhau (và chính xác) trong GHCi hoặc ngược lại. Đối với các tiện ích mở rộng GHC, bạn có thể bật cùng một mặc định mở rộng mà GHCi sử dụng, nhưng tôi không biết tại sao bạn muốn ... –

+0

@Don: Có lẽ bạn có phiên bản/cờ khác nhau?Đối với tôi: X: \ fc3> ghci ___ ___ _ /_ \/\/\/__ (_) // _ \ ///_///| | GHC Interactive, phiên bản 6.4.2, dành cho Haskell 98. // _ \\/__// ___ | | http://www.haskell.org/ghc/ \ ____/\// _/\ ____/| _ | Kiểu :? để được giúp đỡ. Đang tải gói cơ sở-1.0 ... liên kết ... xong. Prelude>: t (== []) (== []) :: (Eq [a]) => [a] -> Bool Prelude> – Ingo

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