Ну, функция:
f g h x y = g (g x) (h y)
или более многословно:
f g h x y = (g (g x)) (h y)
По сути, мы предполагаем, что все четыре параметра (g
, h
, x
и y
) имеют разные типы.Мы также вводим тип вывода для нашей функции (здесь t
):
g :: a
h :: b
x :: c
y :: d
f g h x y :: t
Но теперь мы собираемся выполнить некоторый вывод.Например, мы видим g x
, так что это означает, что есть приложение функции с g
функцией и x
параметром.Это означает, что g
является функцией с типом ввода c
, поэтому мы переопределяем тип от g
до:
g :: a ~ (c -> e)
h :: b
x :: c
y :: d
f g h x y :: t
(здесь тильда ~
означает, что два типато же самое, поэтому a
совпадает с c -> e
)).
Так как g
имеет тип g :: c -> e
, а x
имеет тип c
, это означает, что результатприложение функции g x
имеет тип g x :: e
.
Мы видим другое приложение функции, g
как функцию и g x
как аргумент.Таким образом, это означает, что тип ввода g
(который c
) должен быть равен типу g x
(который e
), следовательно, мы знаем, что c ~ e
, поэтому типы теперь:
c ~ e
g :: a ~ (c -> c)
h :: b
x :: c
y :: d
f g h x y :: t
Теперь мы видим приложение функции с h
функцией и y
аргументом.Это означает, что h
является функцией, а тип ввода совпадает с типом y :: d
, поэтому h
имеет тип d -> f
, что означает:
c ~ e
g :: a ~ (c -> c)
h :: b ~ (d -> f)
x :: c
y :: d
f g h x y :: t
наконецмы видим приложение функции с g (g x)
функцией и h y
аргументом, так что это означает, что тип выходного значения g (g x) :: c
должен быть функцией, с f
в качестве типа ввода и t
в качестве типа вывода, так что это означает, что c ~ (f -> t)
, и, следовательно:
c ~ e
c ~ (f -> t)
g :: a ~ (c -> c) ~ ((f -> t) -> (f -> t))
h :: b ~ (d -> f)
x :: (f -> t)
y :: d
f g h x y :: t
Так что это означает, что, поскольку f
имеет эти параметры g
, h
, x
и y
, типиз f
это:
f :: ((f -> t) -> (f -> t)) -> (d -> f) -> (f -> t) -> d -> t
-- \_________ __________/ \__ ___/ \__ ___/ |
-- v v v |
-- g h x y