Полиморфные типы в Хаскеле
Я наткнулся на эту функцию
iter p f x = if (p x) then x else (iter p f (f x))
и я решил попробовать определить полиморфные типы самостоятельно, чтобы понять концепцию.
Моя мысль была следующей:
Функция принимает 3 параметра, поэтому мы имеем t1 -> t2 -> t3 -> T
p
используется внутри условия if, поэтому он должен возвращатьbool
, следовательноt1 = a -> Bool
f
также тот же тип, что иp
потому что он передается в качестве аргумента в блоке else, поэтомуt2 = a -> Bool
x используется внутри условия if, поэтому он должен возвращать bool, поэтому
t1 = a -> Bool
Но когда я проверил тип в ghci, мне дали тип
iter :: (t -> Bool) -> (t -> t) -> t -> t
Может кто-нибудь, пожалуйста, объясните причину этого.
Спасибо
2 ответа
Функция принимает 3 параметра, поэтому мы имеем t1 -> t2 -> t3 -> T
Это правильно в качестве отправной точки.
p используется внутри условия if, поэтому он должен возвращать bool, поэтому t1 = a -> Bool
Правильный.
f также тот же тип, что и p, поскольку он передается в качестве аргумента в блоке else, поэтому t2 = a -> Bool
Неправильно. f
никогда не используется так же, как p
, В блоке else f
применяется к x
и результат передан в качестве последнего аргумента iter
, Из того, что мы знаем f x
должен быть того же типа, что и x
так f :: a -> a
,
x используется внутри условия if, поэтому он должен возвращать bool, поэтому t1 = a -> Bool
Неправильно. В случае если x
используется только в качестве аргумента p
, Вы установили выше p :: a -> Bool
, Следовательно x :: a
,
Но когда я проверил тип в ghci, мне дали тип
iter:: (t -> Bool) -> (t -> t) -> t -> t
Правильный. Вы также можете написать эту замену t
с a
чтобы быть последовательным в обозначениях - мы использовали a
выше:
iter :: (a -> Bool) -> (a -> a) -> a -> a
Давайте оценим это снова:
iter p f x = if (p x) then x else (iter p f (f x))
iter
принимает три параметра (технически говоря, каждая функция принимает один параметр, но давайте пропустим детали). Так что это действительно имеет тип t1 -> t2 -> t3 -> t
,
Сейчас в if
- then
- else
Заявление, мы видим (p x)
это означает, что p x
должен оценить до логического. Так что это означает, что:
t1 ~ t3 -> Bool
Далее мы видим x
в then
заявление. Это может показаться несущественным, но это так: это означает, что тип вывода t
такой же, как у t3
, так:
t3 ~ t
Теперь это означает, что мы уже получили, что iter
имеет тип:
iter :: (t3 -> Bool) -> t2 -> t3 -> t3
Теперь мы видим в else
Скажите звонок:
iter p f (f x)
Так что это означает, что f
это функция f :: t4 -> t5
, Так как это занимает x
в качестве ввода его тип ввода должен быть t3
и так как результат (f x)
передается iter
функция (которая сама по себе не является той же "заземленной" iter
функция). Итак, мы должны проверить звонок:
iter :: (u3 -> Bool) -> u2 -> u3 -> u3 -- call
Теперь, так как мы называем это с iter p f (f x)
мы определенно знаем, что u3 ~ t3
: так как p
имеет тип t3 -> Bool
, Таким образом, это основание в дальнейшем:
iter :: (t3 -> Bool) -> u2 -> t3 -> t3 -- call
Синус (f x)
используется в качестве третьего аргумента, мы знаем, что тип результата f x
должно быть t3
также. Так f
имеет тип f :: t3 -> t3
, Итак, мы заключаем, что iter имеет тип:
iter :: (t3 -> Bool) -> (t3 -> t3) -> t3 -> t3