Рассмотрим функцию,
add a b = a + b
Это работает:
*Main> add 1 2
3
Однако, если я добавлю сигнатуру типа, указывающую, что я хочу добавить вещи того же типа:
add :: a -> a -> a
add a b = a + b
Я получаю сообщение об ошибке:
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
Итак, GHC ясно может сделать вывод, что мне нужно ограничение типа Num
, так как оно только что сообщило мне:
add :: Num a => a -> a -> a
add a b = a + b
Работает.
Почему GHC требует, чтобы я добавил ограничение типа?Если я занимаюсь общим программированием, то почему оно не может работать для всего, кто знает, как использовать оператор +
?
В программировании на C ++ вы можете сделать это легко:
#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;
}
Компилятор выясняет типы аргументов для add
и генерирует версию функции для этого типа.Кажется, в подходе Хаскелла есть фундаментальное различие, можете ли вы описать его и обсудить компромиссы?Мне кажется, что это было бы решено, если бы GHC просто заполнил для меня ограничение типа, поскольку он, очевидно, решил, что это необходимо.Тем не менее, почему ограничение типа вообще?Почему бы просто не скомпилировать успешно, если функция используется только в допустимом контексте, где аргументы находятся в Num
?