2012-04-29 51 views
5

Tôi không hiểu tại sao các chức năng sau đây hoạt động:Lẫn lộn với Haskell suy luận kiểu

isLongerThanN :: Integral n => n -> [a] -> Bool 
isLongerThanN n xs = length xs > fromIntegral n 

nhưng sau không:

isLongerThanN' :: Integral n => n -> [a] -> Bool 
isLongerThanN' n xs = length xs > n 

mà ném lỗi

Could not deduce (n ~ Int) 
    from the context (Integral n) 
     bound by the type signature for 
       isLongerThanN' :: Integral n => n -> [a] -> Bool 
     at blah.hs:140:1-35 
     `n' is a rigid type variable bound by 
      the type signature for 
      isLongerThanN' :: Integral n => n -> [a] -> Bool 
      at blah.hs:140:1 
    In the second argument of `(>)', namely `n' 
    In the expression: length xs > n 
    In an equation for `isLongerThanN'': 
     isLongerThanN' n xs = length xs > n 

(mà tôi có thể đã hiểu lầm)

Nếu có bất cứ điều gì, tôi mong đợi nó sẽ là một cách khác xung quanh, vì từIntegral đang mở rộng có hiệu quả loại biến n.

+8

Đừng viết 'nếu foo sau đó Đúng khác false'. Nó giống như 'foo'. – hammar

+1

bạn nói đúng, cảm ơn; Tôi đã sửa đổi nó, nhưng đó không phải là câu hỏi – Inept

+4

Đó là lý do tại sao anh ấy không đăng câu trả lời ... – Jasper

Trả lời

12

Hãy xem xét những biểu hiện đó không làm việc

isLongerThanN' :: Integral n => n -> [a] -> Bool 
isLongerThanN' n xs = length xs > n 

n thể được bất kỳ loại nguyên-y, vì vậy nó có thể được thông qua một Integer hoặc Word hoặc Int. (>) có loại Ord a => a -> a -> Bool vì vậy cả toán hạng trái và phải phải cùng loại. length xs trả về một số Int để loại này phải như vậy. Tuy nhiên, n có thể là bất kỳ Integral, không nhất thiết là Int, vì vậy chúng tôi cần một số cách để cho phép n được chuyển đổi thành Int. Đây là những gì fromIntegral làm (thực tế là nó cũng cho phép n được bất kỳ Num về cơ bản là không liên quan).

Chúng ta có thể mở rộng phiên bản làm việc để trông giống như:

toInt :: Integral n => n -> Int 
toInt = fromIntegral 

isLongerThanN :: Integral n => n -> [a] -> Bool 
isLongerThanN n xs = length xs > toInt n 

mà làm cho nó rõ ràng rằng chúng tôi đang sử dụng một phiên bản đặc biệt của fromIntegral.

(Lưu ý rằng isLongerThanN n xs = fromIntegral (length xs) > n cũng làm việc, bởi vì nó cho phép các kết quả của length để phù hợp với các loại n.)

+2

Mặc dù, lưu ý rằng lựa chọn bạn chuyển đổi có thể ảnh hưởng đến kết quả; với ví dụ cuối cùng 'isLongerThanN (0 :: Word8) [1..256] == Sai' do tràn. – hammar

+0

Được rồi, tôi hiểu rồi. Cảm ơn rất nhiều. Tại sao phiên bản không hoạt động không hoạt động không phải là vấn đề đối với tôi, nhưng tôi đã đọc chữ ký kiểu từIntegral :: (Num b, Integral a) => a -> b sai. – Inept