Zobacz tę odpowiedź StackOverflow dotyczącą wnioskowania o typie Go. Sam nie jestem zaznajomiony z Go, ale na podstawie tej odpowiedzi wydaje się, że jest to jednokierunkowa „dedukcja typu” (pożyczyć trochę teminologii w C ++). Oznacza to, że jeśli masz:
x := y + z
następnie typ x
jest wydedukowany przez ustalenie typu y + z
, co jest stosunkowo trywialną rzeczą dla kompilatora. Aby to zrobić, rodzaje y
i z
muszą być z góry znane : można tego dokonać za pomocą adnotacji typu lub wywnioskować z przypisanych im literałów.
Natomiast większość języków funkcjonalnych ma wnioskowanie typu, które wykorzystuje wszystkie możliwe informacje w module (lub funkcji, jeśli algorytm wnioskowania jest lokalny), aby wyprowadzić typ zmiennych. Skomplikowane algorytmy wnioskowania (takie jak Hindley-Milner) często wiążą się z pewną formą unifikacji typów (trochę jak rozwiązywanie równań) za kulisami. Na przykład w Haskell, jeśli napiszesz:
let x = y + z
wtedy Haskell może wywnioskować ten typ nie tylko, x
ale także y
i z
po prostu na podstawie tego, że wykonujesz na nich dodawanie. W tym przypadku:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(Mała litera a
tutaj oznacza typ polimorficzny , często nazywany „ogólnymi” w innych językach, takich jak C ++. Num a =>
Część jest ograniczeniem wskazującym, że a
obsługa typów ma pewne pojęcie dodawania).
Oto bardziej interesujący przykład: kombinator stałoprzecinkowy, który umożliwia zdefiniowanie dowolnej funkcji rekurencyjnej:
let fix f = f (fix f)
Zauważ, że nigdzie nie podaliśmy typu f
ani nie podaliśmy typu fix
, jednak kompilator Haskell może automatycznie stwierdzić, że:
f :: t -> t
fix :: (t -> t) -> t
To mówi, że:
- Ten parametr
f
musi być funkcją od dowolnego dowolnego typu t
do tego samego typu t
.
fix
to funkcja, która odbiera parametr typu t -> t
i zwraca wynik typu t
.
x
,y
,z
są takie sameNum
typ Eric, ale nadal mogą być oneInteger
s,Double
s,Ratio Integer
s ... Haskell jest skłonny do arbitralnego wyboru typów liczbowych, ale nie dla innych typeclasses.Wnioskowanie o typach w Go jest niezwykle ograniczone i niezwykle proste. Działa tylko w jednym konstrukcie językowym (deklaracja zmiennej) i po prostu przyjmuje typ po prawej stronie i wykorzystuje go jako typ zmiennej po lewej stronie.
Wnioskowanie o typach w Haskell może być używane wszędzie, może służyć do wnioskowania o typach dla całego programu. Opiera się na unifikacji, co oznacza, że (koncepcyjnie) wszystkie typy są wywnioskowane „na raz” i mogą one wpływać na siebie nawzajem: w Go informacje o typie mogą przepływać tylko z prawej strony deklaracji zmiennej do lewej- strona strony, nigdy w innym kierunku i nigdy poza deklaracją zmienną; w Haskell informacja o typie przepływa swobodnie we wszystkich kierunkach przez cały program.
Jednak system typów Haskell jest tak potężny, że wnioskowanie typu może faktycznie nie wywnioskować typu (a ściślej: należy wprowadzić ograniczenia, aby zawsze można było wywnioskować typ). System typów Go jest tak prosty (bez podtypów, polimorfizmu parametrycznego), a jego wnioskowanie jest tak ograniczone, że zawsze się udaje.
źródło