Посмотрите этот ответ StackOverflow относительно вывода типа Go. Я сам не знаком с Go, но на основании этого ответа он выглядит как односторонний «вывод типа» (если позаимствовать некоторую терминологию C ++). Это означает, что если у вас есть:
x := y + z
затем тип x
определяется путем выяснения типа y + z
, что довольно легко сделать для компилятора. Для этого типы y
и z
должны быть известны априори : это можно сделать с помощью аннотаций типов или вывести из литералов, назначенных им.
Напротив, большинство функциональных языков имеют вывод типа, который использует всю возможную информацию в модуле (или функцию, если алгоритм вывода является локальным) для получения типа переменных. Сложные алгоритмы вывода (такие как Хиндли-Милнер) часто вовлекают некоторую форму объединения типов (немного похоже на решение уравнений) за кулисами. Например, в Haskell, если вы напишите:
let x = y + z
тогда Haskell может определить тип не только, x
но y
и z
просто, основываясь на том факте, что вы выполняете сложение для них. В этом случае:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(Нижний регистр a
здесь обозначает полиморфный тип , часто называемый «обобщением» в других языках, таких как C ++. Эта Num a =>
часть является ограничением, указывающим, что a
поддержка типа имеет некоторое представление о добавлении.)
Вот более интересный пример: комбинатор с фиксированной точкой, который позволяет определить любую рекурсивную функцию:
let fix f = f (fix f)
Обратите внимание, что нигде мы не указали тип f
и не указали тип fix
, но компилятор Haskell может автоматически выяснить, что:
f :: t -> t
fix :: (t -> t) -> t
Это говорит о том, что:
- Параметр
f
должен быть функцией от произвольного типа t
до того же типа t
.
fix
это функция, которая получает параметр типа t -> t
и возвращает результат типа t
.
x
,y
,z
такая жеNum
тип Эрика, но они все еще могут бытьInteger
s,Double
S,Ratio Integer
S ... Haskell готов сделать произвольный выбор между числовыми типами, но не для других классов типов.