Чтобы определить тип функции, процесс в основном выглядит так:
С учетом функции,
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
предполагается, что все типы параметров и возвращаемое значение неизвестны.
foldr : 'a -> 'b -> 'c -> 'd
f (arg1): 'a
b (arg2): 'b
(arg3): 'c
(return): 'd
fun foldr f b [] = b
Прежде всего, мы видим, что b
(arg2) совпадает с типом возврата foldr
(return) и (arg3) является списком некоторого неизвестного типа.
f (arg1): 'a
b (arg2): 'b
(arg3): 'e list
(return): 'b
| foldr f b (x::xs)
x
и xs
составляют список (arg3).
f (arg1): 'a
b (arg2): 'b
(arg3): 'e list
(return): 'b
x : 'e
xs : 'e list
= f (x, (foldr f b xs))
Тогда f
(arg1) - это функция, которая принимает 2-кортеж и возвращает тот же тип, что и foldr
return (return). Первый элемент кортежа того же типа, что и x
. Второй элемент кортежа того же типа, что и тип возвращаемого значения foldr
(возврат). Типы также сохраняются для рекурсивного вызова foldr
.
f (arg1): 'e * 'b -> 'b
b (arg2): 'b
(arg3): 'e list
(return): 'b
x : 'e
xs : 'e list
fun foldr f b [] = b
| foldr f b (x::xs) = f (x, (foldr f b xs))
Это не может быть упрощено, поэтому у нас есть тип:
Foldr: ('a * 'b -> 'b) -> 'b -> 'a list -> 'b