W pracy miałem za zadanie wnioskować o pewnych typach informacji o dynamicznym języku. Przepisuję sekwencje instrukcji na let
wyrażenia zagnieżdżone , tak jak poniżej:
return x; Z => x
var x; Z => let x = undefined in Z
x = y; Z => let x = y in Z
if x then T else F; Z => if x then { T; Z } else { F; Z }
Ponieważ zaczynam od ogólnych informacji o typie i staram się wydedukować bardziej szczegółowe typy, naturalnym wyborem są typy wyrafinowania. Na przykład operator warunkowy zwraca sumę typów jego prawdziwych i fałszywych gałęzi. W prostych przypadkach działa bardzo dobrze.
Jednak wpadłem na przeszkodę, próbując wywnioskować, co następuje:
function g(f) {
var x;
x = f(3);
return f(x);
}
Który jest przepisany na:
\f.
let x = undefined in
let x = f 3 in
f x
HM wywnioskuje a w konsekwencji . Rzeczywisty typ, który chcę móc wywnioskować, to:
Już używam zależności funkcjonalnych do rozwiązania typu przeciążonego +
operatora, więc doszedłem do wniosku, że naturalnym rozwiązaniem było użycie ich do rozwiązania typu f
wewnątrz g
. Oznacza to, że typy f
wszystkich jego aplikacji razem jednoznacznie określają typ g
. Jednak, jak się okazuje, fundeps nie nadają się zbyt dobrze do zmiennej liczby typów źródeł.
W każdym razie wzajemne oddziaływanie polimorfizmu i typowania udoskonalonego jest problematyczne. Czy brakuje mi lepszego podejścia? Obecnie trawię „Typy wyrafinowania dla ML” i doceniłbym więcej literatury lub innych wskazówek.