Ну, здесь есть три функции:
(.) :: (b -> c) -> (a -> b) -> a -> c
а>;
flip :: (a -> b -> c) -> b -> a -> c
а>; а также
const :: a -> b -> a
.
Обратите внимание, что если вы используете функцию (.)
в качестве оператора, вы на самом деле написали:
(.) flip const
или более подробно:
((.) flip) const
теперь давайте сначала напишем сигнатуры функций подробно и с разными возможными именами, чтобы они не конфликтовали:
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
flip :: (d -> (e -> f)) -> (e -> (d -> f))
const :: g -> (h -> g)
Итак, мы применяем (.)
к flip
, что означает, что мы должны сопоставить параметр (.)
, который имеет тип (b -> c)
, с сигнатурой flip, поэтому мы разрешаем это с помощью:
b -> c
(d -> (e -> f)) -> (e -> (d -> f))
Это единственное возможное совпадение (обратите внимание на скобки). Итак, это означает, что:
b ~ (d -> (e -> f))
c ~ (e -> (d -> f))
(здесь a ~ b
означает, что a
и b
одного типа)
В результате тип (.) flip
равен
(.) flip :: (a -> b) -> (a -> c)
Это снова функция с одним параметром (все функции в Haskell имеют один параметр), и этот параметр имеет тип a -> b
. и мы применяем эту функцию к const
, так что мы снова делаем сопоставление с образцом:
a -> b
g -> (h -> g)
значит, что a ~ g
и b ~ (d -> (e -> f)) ~ (h -> g)
, в результате мы знаем, что d ~ h
и g ~ (e -> f)
.
Мы знаем, что тип ((.) flip) const
имеет тип:
((.) flip) const :: a -> c`
Итак, теперь нужно заменить: a
на g
и g ~ (e -> f)
, то есть a ~ (e -> f)
. Кроме того, мы знаем, что c ~ (e -> (d -> f))
, а это означает, что тип:
((.) flip) const :: (e -> f) -> (e -> (d -> f))
или в менее подробной форме:
flip . const :: (e -> f) -> e -> d -> f
который, за исключением переименования переменных, совпадает с типом, полученным GHCi.
person
Willem Van Onsem
schedule
10.05.2018