2013-07-08 74 views
8

Tôi đang nghiên cứu cách tính năng nạp chồng chức năng mạnh mẽ trong GHC. Tôi đã viết đoạn mã sau:Tại sao chú thích kiểu này trong Haskell cần thiết?

class F_third_arg a where 
    run_f :: (Integer, a) -> Integer 

instance F_third_arg Integer where 
    run_f (_, x) = x 

instance F_third_arg String where 
    run_f (x, _) = x 

my_fun :: (F_third_arg a) => Integer -> (a -> Integer) 
my_fun x = \a -> run_f(x, a) 

main :: IO() 
main = putStrLn $ show(((my_fun::Integer->(Integer->Integer)) 5) $ 6) 

(vâng, tôi cần -XTypeSynonymInstances -XFlexibleInstances) và tôi đã rất ngạc nhiên rằng trình biên dịch cần loại chú thích gần cuộc gọi đến my_fun. Nó được áp dụng cho hai con số - vấn đề với việc suy luận chú thích này là gì? Các quy tắc quá tải với hai phần mở rộng này được bật?

+0

'FlexibleInstances' đã ngụ ý' TypeSynonymInstances'. 'putStrLn. show' tương đương với 'print'. Và bạn có thể bỏ qua khá nhiều parens ... – leftaroundabout

+3

Đối với kiểu ** mặc định ** (dĩ nhiên trình biên dịch không thể _infer_ kiểu: chữ số là đa hình!), Tôi không phải là chuyên gia về điều đó, nhưng GHC mở rộng các quy tắc mặc định thực hiện công việc ('{- # LANGUAGE ExtendedDefaultRules # -}' hoặc GHCi). Một cách tốt hơn sẽ là 'in $ my_fun 5 (6 :: Integer)'. – leftaroundabout

+0

Cảm ơn! Nhận xét của bạn thực sự hữu ích. –

Trả lời

7

Sự cố với mã của bạn là bản thân chữ số đã bị quá tải. Vì vậy, chữ cái 6 theo nghĩa đen có loại Num a => a, trong khi my_fun 5 có loại F_third_arg b => b -> Integer. Vì vậy, trong suy luận kiểu, nó hợp nhất hai biến kiểu này. Nhưng khi không có yêu cầu khác về họ, GHC không thể tìm thấy một loại cụ thể để sử dụng ở đây, và đưa ra một thông báo lỗi thích hợp:

 
test.hs:16:26: 
    No instance for (F_third_arg a0) arising from a use of `my_fun' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance F_third_arg String -- Defined at test.hs:9:10 
     instance F_third_arg Integer -- Defined at test.hs:6:10 
    In the expression: (my_fun 5) 
    In the first argument of `show', namely `((my_fun 5) $ 6)' 
    In the second argument of `($)', namely `show ((my_fun 5) $ 6)' 

test.hs:16:38: 
    No instance for (Num a0) arising from the literal `6' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance Num Double -- Defined in `GHC.Float' 
     instance Num Float -- Defined in `GHC.Float' 
     instance Integral a => Num (GHC.Real.Ratio a) 
     -- Defined in `GHC.Real' 
     ...plus three others 
    In the second argument of `($)', namely `6' 
    In the first argument of `show', namely `((my_fun 5) $ 6)' 
    In the second argument of `($)', namely `show ((my_fun 5) $ 6)' 

Người ta có thể hy vọng rằng trình biên dịch thông báo rằng Integer là loại duy nhất mà đáp ứng cả hai yêu cầu, nhưng các chẩn đoán như vậy sẽ làm cho mã của bạn tương đối mong manh, tức là nó sẽ phá vỡ chỉ vì bạn thêm một cá thể mới (ví dụ: F_third_arg Double). Do đó trình biên dịch từ chối mã và yêu cầu bạn phải rõ ràng về loại được đề cập.

Bạn đã tìm thấy một cách để khắc phục, nhưng đề xuất sử dụng 6::Integer của leftroundabouts đẹp hơn một chút.