Объяснить вывод типа ML программисту на C ++ - PullRequest
5 голосов
/ 20 апреля 2010

Как 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: простите за мой плохой английский; это не мой родной язык.

Ответы [ 4 ]

5 голосов
/ 20 апреля 2010

Предлагаю вам взглянуть на эту статью: Что такое Хиндли-Милнер?(и почему это круто)

Вот самый простой пример, который они используют для объяснения вывода типа (это не ML, но идея та же самая):

def foo(s: String) = s.length
// note: no explicit types
def bar(x, y) = foo(x) + y

ПростоГлядя на определение бара, мы можем легко увидеть, что его тип должен быть (String, Int) => Int.Это вывод типа в двух словах.Прочитайте всю статью для получения дополнительной информации и примеров.

Я не эксперт по C ++, но я думаю, что шаблоны - это что-то еще, что ближе к универсальности / параметричности, а это нечто иное.

5 голосов
/ 21 апреля 2010

Я думаю, что попытка связать вывод типа ML с чем-нибудь в C ++ с большей вероятностью приведет к путанице, чем к пониманию. В C ++ просто нет ничего похожего на вывод типов.

Единственная часть C ++, которая не делает типизацию явной, - это шаблоны, но (по большей части) они поддерживают общее программирование. Шаблон функции C ++, который вы дали, может в равной степени применяться к неограниченному набору типов - например, код, который вы используете NumType в качестве параметра шаблона, но будет работать со строками. Одна программа может создать экземпляр вашего add для добавления двух строк в одном месте и двух чисел в другом месте.

Вывод типа ML не предназначен для общего программирования. В C или C ++ вы явно определяете тип параметра, а затем компилятор проверяет, что все, что вы пытаетесь сделать с этим параметром, разрешено этим типом. ML переворачивает это: он смотрит на то, что вы делаете с параметром, и выясняет, что тип имеет , чтобы вы могли выполнять эти вещи. Если вы пытались делать вещи, которые противоречат друг другу, он скажет вам, что нет типа, который мог бы удовлетворить ограничения.

Это было бы довольно близко к невозможному в C или C ++, в основном из-за всех неявных преобразований типов, которые разрешены. Например, если у меня есть что-то вроде a + b в ML, он может сразу заключить, что a и b должны быть целыми числами - но в C или C ++ они могут быть практически любой комбинацией целых, указателей или плавающих типы точек (с ограничением, что они не могут оба быть указателями) или используемые определенные типы, которые перегружают operator+ (например, std::string). В ML поиск типов может быть экспоненциальным в худшем случае, но почти всегда довольно быстрым. В C ++ я бы оценил его как экспоненциальный гораздо чаще, и во многих случаях он, вероятно, будет недостаточно ограничен, поэтому данная функция может иметь любую из множества разных сигнатур.

4 голосов
/ 20 апреля 2010

ML использует вывод типа Хиндли-Милнера . В этом простом случае все, что нужно сделать, - это просмотреть тело функции и увидеть, что она использует + с аргументами и возвращает это. Таким образом, можно сделать вывод, что аргументы должны быть типом аргументов, которые + принимает (т.е. целые числа), а функция возвращает тип, который + возвращает (также int). Таким образом, предполагаемый тип add равен int -> int -> int.

Обратите внимание, что в SML (но не в CAML) + также определено для других типов, кроме int, но оно все равно будет выводить int, когда существует несколько возможностей (то есть определенная вами функция add не может использоваться для добавления два поплавка).

0 голосов
/ 21 апреля 2010

F # и ML несколько похожи в отношении вывода типов, поэтому вы можете найти

Обзор вывода типов в F #

полезным.

...