Спасибо всем, кто ответил на мой вопрос.Я изучил ваши ответы.Чтобы быть уверенным, что я понимаю то, что я узнал, я написал свой ответ на свой вопрос.Если мой ответ неправильный, пожалуйста, дайте мне знать.
Мы начнем с типов k
и s
:
k :: t1 -> t2 -> t1
k = (\a x -> a)
s :: (t3 -> t4 -> t5) -> (t3 -> t4) -> t3 -> t5
s = (\f g x -> f x (g x))
Давайте сначала поработаем над определением сигнатуры типа(s k)
.
Напомним определение s
:
s = (\f g x -> f x (g x))
Подстановка k
для f
приводит к (\f g x -> f x (g x))
, заключающемуся в:
(\g x -> k x (g x))
Важно Тип g и x должен соответствовать сигнатуре k
.
Напомним, что k
имеет сигнатуру этого типа:
k :: t1 -> t2 -> t1
Итак, для этого определения функции k x (g x)
мы можем вывести:
Тип x
- это тип первого аргумента k
, который является типом t1
.
Тип второго аргумента k
- t2
, поэтому результат (g x)
должен быть t2
.
g
имеет x
в качестве аргумента, который мы уже определили, имеет тип t1
.Таким образом, сигнатура типа (g x)
равна (t1 -> t2)
.
Тип результата k
равен t1
, поэтому результат (s k)
равен t1
.
Итак, сигнатура типа (\g x -> k x (g x))
такова:
(t1 -> t2) -> t1 -> t1
Далее, k
определено так, чтобы всегда возвращать свой первый аргумент.Так вот:
k x (g x)
заключает контракт с этим:
x
И вот это:
(\g x -> k x (g x))
заключает контракт с этим:
(\g x -> x)
Хорошо, теперь мы выяснили (s k)
:
s k :: (t1 -> t2) -> t1 -> t1
s k = (\g x -> x)
Теперь давайте определим сигнатуру типа s (s k)
.
Мы действуем таким же образом.
Напомним, что определение s
:
s = (\f g x -> f x (g x))
Подстановка (s k)
для f
приводит к (\f g x -> f x (g x))
сокращению до:
(\g x -> (s k) x (g x))
Важно типы g
и x
должны соответствовать сигнатуре типа (s k)
.
Напомним, что (s k)
имеет сигнатуру этого типа:
s k :: (t1 -> t2) -> t1 -> t1
Итак, для этогоопределение функции (s k) x (g x)
мы можем вывести:
Тип x
является типом первого аргумента (s k)
, который является типом (t1 -> t2)
.
Тип второго аргумента (s k)
- t1
, поэтому результат (g x)
должен быть t1
.
g
имеет x
в качестве аргумента, который, как мы уже определили, имеет тип (t1 -> t2)
.Таким образом, сигнатура типа (g x)
равна ((t1 -> t2) -> t1)
.
Тип результата (s k)
равен t1
, поэтому результат s (s k)
равен t1
.
Итак, сигнатура типа (\g x -> (s k) x (g x))
такова:
((t1 -> t2) -> t1) -> (t1 -> t2) -> t1
Ранее мы определили, что s k
имеет это определение:
(\g x -> x)
То есть это функция, которая принимает два аргумента и возвращает второй.
Следовательно, это:
(s k) x (g x)
Контракты на это:
(g x)
И это:
(\g x -> (s k) x (g x))
с этим договаривается:
(\g x -> g x)
Хорошо, теперь мы выяснили s (s k)
.
s (s k) :: ((t1 -> t2) -> t1) -> (t1 -> t2) -> t1
s (s k) = (\g x -> g x)
Наконец, сравнитесигнатура типа s (s k)
с сигнатурой типа этой функции:
p = (\g x -> g x)
Тип p
:
p :: (t1 -> t) -> t1 -> t
p
и s (s k)
имеюттакое же определение (\g x -> g x)
так почему же они имеют разные сигнатуры типов?
Причина, по которой s (s k)
имеет сигнатуру другого типа, чем p
, заключается в том, что на p
нет никаких ограничений.Мы видели, что s
в (s k)
ограничено, чтобы соответствовать сигнатуре типа k
, а первое s
в s (s k)
ограничено, чтобы соответствовать сигнатуре типа (s k)
.Таким образом, сигнатура типа s (s k)
ограничена из-за своего аргумента.Даже если p
и s (s k)
имеют одно и то же определение, ограничения для g
и x
различаются.