2015-02-11 20 views
10

Ý tôi là, ví dụ,Tại sao f = (+) không cần chú thích kiểu?

f :: (Enum a) => a -> a --without this line, there would be an error 
f = succ 

Nó vì succ cần tham số của nó sẽ được đếm được (succ :: (Enum a) => a -> a)

nhưng đối với (+)

f = (+) --ok 

Mặc dù tuyên bố (+) 's là (+) :: (Num a) => a –> a –> a.

Ý tôi là, tại sao tôi không cần khai báo ff :: (Num a) => a –> a –> a?

Trả lời

14

Do đặt mặc định.Num là một loại lớp 'mặc định', có nghĩa là nếu bạn để nó không bị ràng buộc, trình biên dịch sẽ thực hiện một vài dự đoán thông minh như loại bạn định sử dụng nó như là. Thử đặt định nghĩa đó trong mô-đun, sau đó chạy

:t f 

trong ghci; nó sẽ cho bạn biết (IIRC) f :: Integer -> Integer -> Integer. Trình biên dịch không biết a nào bạn muốn sử dụng, vì vậy, nó đoán được Integer; và kể từ đó đã làm việc, nó đã đi với đoán đó.

Tại sao nó không suy ra một loại đa hình cho f? Bởi vì hạn chế monomorphism sợ hãi [1]. Khi trình biên dịch thấy

f = (+) 

nó nghĩ 'f là giá trị', có nghĩa là nó cần một loại đơn (monomorphic). Eta-mở rộng định nghĩa để

f x = (+) x 

và bạn sẽ nhận được các loại đa hình

f :: Num a => a -> a -> a 

và tương tự nếu bạn eta-mở rộng định nghĩa đầu tiên bạn

f x = succ x 

bạn không cần phải có gõ chữ ký nữa.

[1] Tên thực tế từ tài liệu GHC!

+0

Khi nào việc giảm này xảy ra chính xác? 'f = (+)' trong ghci không bị giới hạn. – Bergi

+1

@Bergi - câu trả lời ở đây: http://stackoverflow.com/questions/28336108/why-is-22-0-double-in-a-hs-file-but-fractional-aa-in-ghci/28336620 # 28336620 –

7

Ý tôi là, tại sao tôi không cần khai báo f(+) :: (Num a) => a –> a –> a?

Bạn cần làm điều đó, nếu bạn khai báo chữ ký là f. Nhưng nếu bạn không, trình biên dịch sẽ “ đoán ” chữ ký chính nó – trong trường hợp này không phải là tất cả để đáng kể vì nó về cơ bản chỉ cần sao chép & dán chữ ký của (+). Và đó là chính xác những gì nó sẽ làm.

... hoặc ít nhất là việc cần làm. Nó có, miễn là bạn có cờ -XNoMonomorphism. Nếu không, tốt, các bước dreaded monomorphism restriction do định nghĩa của f là hình dạng ConstantApplicativeForm = Value; mà làm cho trình biên dịch câm xuống chữ ký để tiếp theo tốt nhất không đa hình loại nó có thể tìm thấy, cụ thể là Integer -> Integer -> Integer. Để ngăn chặn điều này, bạn thực tế nên cung cấp chữ ký phù hợp bằng tay, cho tất cả các chức năng cấp cao nhất. Điều đó cũng ngăn cản rất nhiều sự nhầm lẫn và nhiều lỗi trở nên khó hiểu hơn.

Hạn chế monomorphism là lý do

f = succ 

sẽ không làm việc trên riêng của mình: bởi vì nó cũng có hình dạng CAF này, trình biên dịch không cố gắng để suy ra kiểu đa hình chính xác, nhưng cố gắng để tìm thấy một số sự khởi tạo cụ thể để tạo ra một chữ ký đơn sắc. Nhưng không giống như Num, lớp Enum không cung cấp trường hợp mặc định.

giải pháp có thể, sắp xếp theo sở thích:

  1. Luôn luôn thêm chữ ký. Bạn thực sự cần.
  2. Bật -XNoMonomorphismRestriction.
  3. Viết định nghĩa chức năng của bạn ở dạng f a = succ a, f a b = a+b. Bởi vì có được đề cập một cách rõ ràng lý lẽ, những không đủ điều kiện như CAF, do đó hạn chế monomorphism sẽ không kick trong.
  4. mặc định
0

Haskell Num trở ngại đối với Int hoặc Integer, tôi quên được.

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