Как делает ML, выполняют вывод типа в следующем функциональном определении:
let add a b = a + b
Похож на это шаблоны C++, где никакая проверка типа не выполняется до точки шаблонного инстанцирования, после которого, если тип поддерживает необходимые операции, функциональные работы или иначе ошибку компиляции, брошен?
т.е. например, следующий шаблон функции
template <typename NumType>
NumType add(NumType a, NumType b) {
return a + b;
}
будет работать на
add<int>(23, 11);
но не будет работать на
add<ostream>(cout, fout);
То, что я предполагаю, корректно, или вывод типа ML работает по-другому?
PS: Извините за мой плохой английский язык; это не мой родной язык.
Предлагаю вам взглянуть на эту статью: Что такое Хиндли-Милнер? (и почему это круто)
Вот простейший пример, который они используют для объяснения вывода типов (это не ML, но идея та же самая):
def foo(s: String) = s.length
// note: no explicit types
def bar(x, y) = foo(x) + y
Просто взглянув на определение bar, мы легко увидим, что его тип должен быть (String, Int) => Int. Вкратце, это вывод типа. Прочтите всю статью для получения дополнительной информации и примеров.
Я не эксперт по C ++, но думаю, что шаблоны - это нечто иное, что ближе к универсальности / параметричности, а это нечто иное.
F # и ML в чем-то похожи в отношении вывода типов, поэтому вы можете найти
полезным.
Я думаю, что попытка связать вывод типа ML практически с чем угодно в C ++ более вероятна чтобы привести к путанице, чем к пониманию. В C ++ просто нет ничего похожего на вывод типов.
Единственная часть C ++, которая не делает явной типизацию, - это шаблоны, но (по большей части) они поддерживают общие Шаблон функции C ++, подобный приведенному вами, может в равной степени применяться к неограниченному набору типов - например, в вашем коде в качестве параметра шаблона используется NumType
, но он будет работать со строками. одна программа может создать экземпляр вашего add
, чтобы добавить две строки в одном месте и два числа в другом месте.
ML тип i Ссылка не предназначена для общего программирования. В C или C ++ вы явно определяете тип параметра, а затем компилятор проверяет, что все, что вы пытаетесь сделать с этим параметром, разрешено этим типом.ML меняет это положение на противоположное: он смотрит на то, что вы делаете с параметром, и выясняет, каким должен быть тип , чтобы вы могли делать эти вещи. Если вы пытались делать что-то, что противоречит друг другу, он скажет вам, что не существует типа, который мог бы удовлетворить ограничениям.
Это было бы почти невозможно в C или C ++, в основном из-за всех разрешенных неявных преобразований типов. Например, если у меня есть что-то вроде a + b
в ML, он может сразу сделать вывод, что a
и b
должны быть целыми числами, но в C или В C ++ они могут быть практически любой комбинацией целочисленных типов, типов указателей или типов с плавающей запятой (с ограничением, что они не могут оба быть указателями) или использовать определенные типы, которые перегружают оператор +
(например, , std :: string
). В машинном обучении поиск типов в худшем случае может быть экспоненциальным, но почти всегда довольно быстрым. В C ++ я бы оценил, что это экспоненциально гораздо чаще, и во многих случаях, вероятно, будет недостаточно ограниченным, поэтому данная функция может иметь любую из множества различных сигнатур.
ML использует вывод типа Хиндли-Милнера . В этом простом случае все, что ему нужно сделать, это посмотреть на тело функции и увидеть, что она использует +
с аргументами и возвращает их. Таким образом, можно сделать вывод, что аргументы должны быть типа аргументов, которые принимает +
(т.е. целые числа), а функция возвращает тип, который возвращает +
(также int). Таким образом, предполагаемый тип add
- int -> int -> int
.
Обратите внимание, что в SML (но не CAML) +
также определен для других типов, кроме int, но он все равно будет выводить int, когда есть несколько возможностей (например, функция add
вы определили, что нельзя использовать для добавления двух поплавков).