2011-11-30 35 views
5

Đối với các định nghĩa hàm thông thường sau:Sự khác nhau giữa hai định nghĩa kiểu hàm này là gì?

printLength1::(Num a)=>String->a 
printLength1 s = length s 


printLength2::String->Int 
printLength2 s = length s 

Tại sao họ lại không giống nhau? Trong tình huống nào tôi nên chọn cái này qua cái kia?

Và tôi nhận được lỗi này cho printLength1:

Couldn't match type `a' with `Int' 
     `a' is a rigid type variable bound by 
      the type signature for rpnc :: String -> a at test.hs:20:1 
    In the return type of a call of `length' 
    In the expression: length s 
    In an equation for `rpnc': rpnc s = length s 

Tôi hiểu lỗi này. Nhưng làm thế nào tôi có thể sửa lỗi này? Tôi đã đọc một số bài đăng ở đây về biến loại cứng nhắc nhưng vẫn không thể hiểu cách khắc phục.

Trả lời

9

Chữ ký loại đầu tiên tổng quát hơn. Nó có nghĩa là kết quả có thể là bất kỳ Num - đó là đa hình trên kiểu trả về của nó. Vì vậy, kết quả của chức năng đầu tiên của bạn có thể được sử dụng làm Int hoặc Integer hoặc bất kỳ trường hợp nào khác Num.

Sự cố là length trả lại Int thay vì bất kỳ trường hợp Num nào. Bạn có thể sửa lỗi này bằng fromIntegral:

printLength1 :: Num a => String -> a 
printLength1 s = fromIntegral $ length s 

Lưu ý rằng chữ ký của fromIntegral . length (đó là phiên bản điểm miễn phí của mã ở trên) là Num c => [a] -> c. Điều này khớp với chữ ký bạn đã chỉ định cho hàm printLength1 của bạn.

+0

Xin cảm ơn các bạn. Tôi hy vọng không còn những ẩn số như vậy trong ngôn ngữ. – osager

+3

@osager Đây không phải là một điều kỳ quặc, đây là một phần cơ bản quan trọng của hệ thống kiểu. Các loại đa hình (ít nhất là loại đa hình bậc 1) được biến thành các loại bê tông theo cách chúng được sử dụng. Nếu bạn viết một chữ ký kiểu xác nhận rằng một loại là đa hình, nó cần phải thực sự * là * đa hình. – Carl

+1

Lớp 'Num' không phải là một quirk, nhưng bạn có thể lý luận cho rằng' length' là một 'Int' chứ không phải là một' Num a' là một quirk. –

7

Trích dẫn LearnYouAHaskell.com:

Lưu ý: Chức năng này có một loại numLongChains :: Int vì chiều dài trả về một Int thay vì một Num một vì những lý do lịch sử. Nếu chúng ta muốn trả về một số tổng quát hơn, chúng ta có thể đã sử dụng từIntegral trên độ dài kết quả.

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