2013-06-23 31 views
9
take :: Int -> [a] -> [a] 
genericTake :: Integral i => i -> [a] -> [a] 

Tôi đã đọc rằng loại bất tiện của take là do lý do lịch sử và việc thay đổi nó có thể khiến một số mã bị hỏng.Tại sao không thể thay đổi loại hình để sử dụng bất kỳ Tích phân nào?

Nhưng tôi không thể thay thế take bằng genericTake ở mọi nơi mà không vi phạm bất cứ điều gì? Có chuyện gì vậy?

+0

Tôi đoán có thể có một trường hợp bắt nguồn kiểu dựa trên kiểu 'take' - với' genericTake' một cái gì đó của loại "không thể lấy được" sẽ xảy ra. – leventov

+4

Lưu ý rằng ngoài (và có lẽ thực tế có liên quan nhiều hơn) code breakage trong trường hợp tối nghĩa, thay thế 'take' bằng' genericTake' sẽ dẫn đến sự xuống cấp hiệu suất trong nhiều trường hợp (vì việc mặc định kiểu sẽ dẫn đến 'Integer' được sử dụng khi không chỉ định ':: Int'). – sepp2k

Trả lời

10

Một trường hợp bẻ

genericTake :: Integral i => i -> [a] -> [a] 
genericTake n xs = take (fromIntegral n) xs 

class Foo a where 
    bar :: a -> String 

instance Foo Int where 
    bar _ = "int" 

foo :: String -> [a] -> [a] 
foo ns xs = let y = read ns 
       z = bar y 
      in take y xs 

này sẽ phá vỡ cho genericTake.

No instance for (Foo i0) arising from a use of `bar' 
    The type variable `i0' is ambiguous 

Đây là một nấu chín lên ví dụ nhưng bạn có thể hiểu được một số loại suy luận xảy ra trên đối số đầu tiên cất nơi người ta cho rằng nó là Int, bây giờ khi bạn thay đổi loại để Integral i => i một số vấn đề có thể xảy ra như trên.

+0

+1 Đây là một nỗi đau thực sự với các trường hợp loại, và tôi muốn nó đã được cố định. – jpaugh

+0

@jpaugh Bạn đề nghị sửa chữa cái gì? Tôi không chắc chắn nếu nó có thể được cố định. – Satvik

+0

Đã không cố gắng này, nhưng sẽ không biên dịch này với các quy tắc mặc định mở rộng? –

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