Расширение комментариев под хорошим ответом Намина:
Итак, предположим, что функция имеет тип 'a -> ('a * 'a)
:
let gimme_tuple(a : int) =
(a*2, a*3)
Тогда предположим, что функция имеет тип ('a * 'a) -> 'b
:
let add(a : int, b) =
a + b
Тогда композиция (при условии, что предложенное мной объединение) не создаст никаких проблем, насколько я вижу:
let foo = add(gimme_tuple(5))
// foo gets value 5*2 + 5*3 = 25
Но тогда вы можете представить себе полиморфную функцию, которая занимает место add
в последнем фрагменте кода, например, небольшую функцию, которая просто принимает 2-кортеж и составляет список из двух элементов:
let gimme_list(a, b) =
[a, b]
Это будет иметь тип ('a * 'a) -> ('a list)
. Состав сейчас будет проблематичным. Рассмотрим:
let bar = gimme_list(gimme_tuple(5))
Будет ли bar
иметь значение [10, 15] : int list
или будет bar
функцией типа (int * int) -> ((int * int) list)
, которая в конечном итоге выдаст список, заголовком которого будет кортеж (10, 15)
? Чтобы это сработало, в комментарии к ответу Намина я указывал, что в системе типов потребуется дополнительное правило, согласно которому привязка фактических к формальным параметрам должна быть «максимально возможной», т. Е. Что система должна предпринимать попытки частичного связывания. сначала и только попробуйте частичное связывание, если полное связывание недостижимо. В нашем примере это будет означать, что мы получим значение [10, 15]
, поскольку в этом случае возможна полная привязка.
Является ли такое понятие "максимально возможного" бессмысленным по своей природе? Я не знаю, но я не могу сразу увидеть причину, по которой это будет.
Одна проблема, конечно, если вы хотите вторую интерпретацию последнего фрагмента кода, то вам нужно перепрыгнуть через дополнительный обруч (обычно анонимную функцию), чтобы получить это.