Hãy xem xét các chức năng,trong haskell, tại sao tôi cần phải xác định ràng buộc kiểu, tại sao trình biên dịch không thể tìm ra chúng?
add a b = a + b
này hoạt động:
*Main> add 1 2
3
Tuy nhiên, nếu tôi thêm một loại chữ ký xác định rằng tôi muốn thêm thứ cùng loại:
add :: a -> a -> a
add a b = a + b
Tôi gặp lỗi:
test.hs:3:10:
Could not deduce (Num a) from the context()
arising from a use of `+' at test.hs:3:10-14
Possible fix:
add (Num a) to the context of the type signature for `add'
In the expression: a + b
In the definition of `add': add a b = a + b
Vì vậy, GHC rõ thể suy ra rằng tôi cần Num
loại hạn chế, vì nó chỉ nói với tôi:
add :: Num a => a -> a -> a
add a b = a + b
trình.
Tại sao GHC yêu cầu tôi thêm ràng buộc loại? Nếu tôi đang làm lập trình chung chung, tại sao nó không thể làm việc cho bất cứ điều gì mà biết làm thế nào để sử dụng các nhà điều hành +
?
Trong C++ template lập trình, bạn có thể làm điều này một cách dễ dàng:
#include <string>
#include <cstdio>
using namespace std;
template<typename T>
T add(T a, T b) { return a + b; }
int main()
{
printf("%d, %f, %s\n",
add(1, 2),
add(1.0, 3.4),
add(string("foo"), string("bar")).c_str());
return 0;
}
Những con số trình biên dịch ra các loại của các đối số để add
và tạo ra một phiên bản của hàm cho loại đó. Dường như có một sự khác biệt cơ bản trong cách tiếp cận của Haskell, bạn có thể mô tả nó và thảo luận về sự cân bằng? Dường như với tôi như nó sẽ được giải quyết nếu GHC chỉ đơn giản là điền vào các ràng buộc loại cho tôi, vì nó rõ ràng là quyết định nó là cần thiết. Tuy nhiên, tại sao các ràng buộc loại ở tất cả? Tại sao không chỉ biên dịch thành công miễn là hàm chỉ được sử dụng trong ngữ cảnh hợp lệ trong đó các đối số nằm trong Num
?
Tại sao nó nên biến chữ ký kiểu thành một cái gì đó ít chung hơn bằng cách thêm một ràng buộc * khi bạn nói rõ ràng rằng bạn không muốn ràng buộc * (bằng cách khai báo 'add :: a -> a -> a')? Cũng lưu ý rằng trong Haskell, không có điều có '(+)' quá tải nhưng không phải là một thể hiện của 'Num' (vì' (+) 'là trong' Num', do đó, để quá tải nó, bạn phải khai báo một 'Num' instance). – delnan