2013-04-17 36 views
7

Tại sao biên dịch sau:Haskell - Biến loại mơ hồ, tại sao?

{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE OverlappingInstances #-} 

class IsList a where 
    isList :: a -> Bool 

instance IsList a where 
    isList x = False 

instance IsList [a] where 
    isList x = True 

main = print (isList 'a') >> print (isList ['a']) 

Nhưng thay đổi main để this:

main = print (isList 42) >> print (isList [42]) 

Cung cấp cho các lỗi sau:

Ambiguous type variable `a0' in the constraints: 
    (Num a0) arising from the literal `42' at prog.hs:13:22-23 
    (IsList a0) arising from a use of `isList' at prog.hs:13:15-20 
Probable fix: add a type signature that fixes these type variable(s) 
In the first argument of `isList', namely `42' 
In the first argument of `print', namely `(isList 42)' 
In the first argument of `(>>)', namely `print (isList 42)' 

isList chắc chắn không có trong lớp Num là là nó? Và nếu không, tại sao sự mơ hồ?

Trả lời

10

Vấn đề không phải là với isList nhưng với hằng số 42. Hằng số 'a' có kiểu Char cụ thể. Hằng số 42 không có loại bê tông.

ghci> :t 42 
42 :: Num a => a 

Trình biên dịch cần một loại cụ thể. Nó sẽ hoạt động nếu bạn thay đổi chính thành các mục sau:

main = print (isList (42 :: Int)) >> print (isList [42 :: Int]) 
+0

Ah, cảm ơn, điều đó có ý nghĩa. Nó có thể biên dịch nếu nó không biết loại của nó. Nhưng tại sao không "mặc định" làm việc ở đây? Tại sao không mặc định là Integer? – Clinton

+0

Trình biên dịch không có bất cứ điều gì chỉ ra rằng nó nên coi đó là một Int. Nếu cùng một định danh là ... nói ... được chuyển vào một hàm cần Int, thì kiểu đó sẽ được hợp nhất thành Int. Nhưng nó sẽ không làm cho giả định đó cho bạn một cách tự động. – mightybyte

+9

@Clinton: Việc mặc định chỉ được thực hiện nếu tất cả các ràng buộc chỉ tham chiếu đến các lớp tiêu chuẩn. 'IsList' không phải là một lớp tiêu chuẩn. Yêu cầu này có thể được thư giãn với 'ExtendedDefaultRules'. – hammar

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