Как работает алгоритм Хиндли-Милнера, когда есть перегруженные функции?
В простой форме (без перегрузок) выглядит чисто:
y = arr[x1] //it's Generic. x1: int, arr: T[], y:T
z = y+1// z:int, y:int => T:int, arr: int[]. Oh. All types are solved
но я не нашел объяснений, как это работает с перегруженными функциями.
Например: у меня 4 перегрузки функции '+':
+(int, int):int
+(int64, int64):int64
+(double, double):double
+(any,any):string
пример:
y = x1+ x2 //x1 and x2 can be int32, int64, real, or objects for string concat
z = x1<<2 //oh! it seems x1 is int!
m = not x2 //omg, x2 is bool. That means that y = 2 + true = '2true' i.e. Ty:string
или сложный случай:
//functions:
myfun(x,y) = x<<y //(int,int)->int
myfun(x,y) = "some: " + y.toLower() + not x //(bool,string)-> string
//body:
y1 = myfun(x1,x2) //or (int,int)->int or (bool,string)-> string
y2 = myfun(x3,y1) //or (int,int)->int or (bool,string)-> string
y3 = if (x3) 1 else 0 //x3: bool, y3: string
//x3:bool => y2:string, y1:string
//y1:string=> x1:bool, x2:string
Беда в том, что я должен помнить все эти случаи:
y1 cases:
int if x1: int and x2:int
string if x1: bool and x2:string
y2 cases:
int if x3: int and y1:int
string if x3: bool and y1:string
и случаи y2 относятся к случаям y1, и это похоже на дерево уравнений, которое звучит страшно.
Есть ли формализация таких алгоритмов?