Вывод типа Хиндли-Милнера используется для систем типа Хиндли-Милнера, ограничение систем типа System-F. Интересной особенностью систем типа HM является то, что они имеют параметрический полиморфизм (он же дженерики). Это единственная особенность системы типов, которую Голанг отказывается иметь.
С этим разочаровывающим ограничением вывод типа HM невозможен. Давайте посмотрим на нетипизированный код:
func f(a) {
return a.method()
}
Какой тип f
? Мы могли бы заметить , что a
должен иметь метод, чтобы мы могли использовать анонимный интерфейс: func f(a interface { method() ??? }) ???
. Однако мы понятия не имеем, что такое тип возвращаемого значения. С переменными типа мы могли бы объявить тип как
func f[T](a interface{ method() T }) T
Однако в Go нет переменных типа, поэтому это не сработает. Несмотря на то, что неявные интерфейсы облегчают некоторые аспекты вывода типов, у нас теперь нет возможности узнать тип возврата вызова функции. HM-система требует, чтобы все функции были объявлены, а не подразумевались, и каждое имя может иметь только один тип (тогда как методы Go могут иметь разные типы в разных интерфейсах).
Вместо этого Go требует, чтобы функции всегда были полностью объявлены, но позволяет переменным использовать вывод типа. Это возможно, потому что правая часть назначения variable := expression
уже имеет известный тип в этой точке программы. Этот тип вывода типа является простым, правильным и линейным.
- Тип переменной сразу известен в точке объявления, тогда как вывод HM должен сначала проверить тип всей программы. Это также заметно влияет на качество сообщений об ошибках.
- Подход с выводом типа в Go всегда будет выбирать наиболее конкретный тип для переменной, в отличие от HM, который выбирает наиболее общий тип. Это чисто работает с подтипами, даже с неявными интерфейсами Go.