2013-05-29 26 views
19

Tôi có một câu hỏi về cách GHCi giả định loại của một số nguyên.Haskell: CóKhông có loại lớp. Tại sao lại là Integer?

Tôi đã đọc Có-Không có loại lớp nào Tìm hiểu bạn một Haskell.

Đây là liên kết nếu bạn muốn đọc toàn bộ nội dung. http://learnyouahaskell.com/making-our-own-types-and-typeclasses#a-yes-no-typeclass

Để đặt nhanh, chương này cho thấy rằng bằng cách xác định lớp của riêng tôi, tôi có thể tạo một hàm hoạt động với nhiều loại.

cuốn sách này định nghĩa lớp CóKhông với một chức năng

yesno :: a -> Bool 

và làm Int như một thể hiện của lớp CóKhông

instance YesNo Int where 
    yesno 0 = False 
    yesno _ = True 

Khi tôi nạp này trên GHCi tôi và gõ

yesno 0 

nó trả về lỗi. Tôi nghĩ có thể là do GHCi không thể biết liệu 0 có phải là Int hoặc Integer hoặc Double hoặc loại khác trong lớp Num. Trên thực tế khi tôi gõ yesno (0 :: Int) nó hoạt động.

Vì vậy chỉ để cho vui Tôi làm Integer như một thể hiện của YesNo lớp và viết

instance YesNo Integer where 
    yesno 0 = True 
    yesno _ = False 

(Lưu ý rằng tôi lật True và False) và một lần nữa, tôi gõ

yesno 0 

(mà không bất kỳ tuyên bố kiểu nào) thì GHCi đã cho thấy True.

Hơn nữa, khi tôi gõ

yesno $ fromIntegral 0 

nó trở True, có nghĩa là GHCi nghĩ loại fromIntegral 0Integer.

Vì vậy, điều này có nghĩa là khi tôi chỉ nhập một số nguyên trên GHCi, nó thường giả định giá trị của nó là Integer thay vì? Tôi bối rối vì :t 0 trả về Num a => a

Trả lời

24

Đó là loại defaulting cùng với các quy tắc mặc định mở rộng của ghci.

Chữ số nguyên là đa hình, chúng có loại Num a => a (vì chúng có giá trị fromInteger literal). Nhưng khi một biểu thức được đánh giá - cần thiết để in kết quả của nó, ví dụ - biểu thức phải được đưa ra một kiểu đơn hình.

Bằng cách riêng của mình,

yesno 0 

áp đặt hai chế Num aYesNo a trên 0, và toàn bộ biểu thức sẽ có các loại mơ hồ

yesno 0 :: (Num a, YesNo a) => Bool 

(đó là mơ hồ, kể từ khi loại biến trong không thể truy cập ràng buộc từ loại ở bên phải của =>).

Nói chung, các loại mơ hồ là lỗi loại, tuy nhiên, trong một số trường hợp, sự mơ hồ được giải quyết bằng cách khởi tạo biến loại bị ràng buộc với loại mặc định. Các quy tắc trong đặc tả ngôn ngữ là một loại biến có thể được mặc định nếu

Trong tình huống mà một loại mơ hồ được phát hiện, một loại biến mơ hồ, v, là defaultable nếu:

- `v` appears only in constraints of the form `C v`, where `C` is a class, and 
- at least one of these classes is a numeric class, (that is, `Num` or a subclass of `Num`), and 
- all of these classes are defined in the Prelude or a standard library (Figures 6.2–6.3 show the numeric classes, and Figure 6.1 shows the classes defined in the Prelude.) 

Ràng buộc (Num a, YesNo a) đáp ứng hai yêu cầu đầu tiên, nhưng không đáp ứng yêu cầu thứ ba. Vì vậy, theo tiêu chuẩn ngôn ngữ, nó không phải là mặc định và nên là một loại lỗi.

Tuy nhiên, ghci sử dụng các quy tắc mặc định mở rộng và cũng mặc định các biến kiểu bị ràng buộc bởi các lớp không được xác định trong Prelude hoặc thư viện chuẩn.

Sau đó nó sẽ chọn mặc định cho một Num hạn chế ở đây, trừ trường hợp khai báo mặc định rõ ràng là trong phạm vi, đó sẽ là Integer, hoặc, nếu Integer không đáp ứng các ràng buộc, Double được xét xử.

Vì vậy, khi bạn có instance YesNo Integer, Ghci có thể mặc định thành công biến loại a đến Integer. Nhưng không có trường hợp như vậy, mặc định không thành công vì không có ứng viên mặc định nào có thể hiện.

8

Vì vậy, điều này có nghĩa là khi tôi chỉ nhập một số nguyên trên GHCi, nó thường giả định giá trị của nó là Số nguyên?

Có. Về cơ bản, GHCi trước tiên sẽ thử Integer, sau đó nếu không thành công, Double và sau đó cuối cùng là () để giải quyết các ràng buộc loại mơ hồ. Bạn có thể read the details about how this works in the GHC User's Guide.

Tuy nhiên, lưu ý rằng trong các mô-đun được biên dịch, các quy tắc hơi chặt chẽ hơn. Đặc biệt, việc mặc định chỉ áp dụng cho các lớp tiêu chuẩn, vì vậy ví dụ của bạn sẽ không hoạt động nếu không có chú thích kiểu trong mô-đun được biên dịch trừ khi bạn bật tiện ích mở rộng ExtendedDefaultRules mang lại cho bạn hành vi tương tự như GHCi.

1

trong trường hợp đầu tiên cố gắng viết:

Prelude> yesno (0 :: Int) 
False 
Các vấn đề liên quan