Каков тип композиции двух функций - например (flip. Const) - PullRequest
0 голосов

Я начал изучать Haskell, и мне интересно, как узнать тип композиции функций: например:

:t flip
flip :: (a -> b -> c) -> b -> a -> c

:t const
const :: a -> b -> a

как вручную сделать :t (flip . const)?

Конечно, GHCi может помочь вам в этом:

:t (flip.const)
(flip . const) :: (b -> c) -> b -> a -> c

а как это сделать самостоятельно?

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

У нас также есть (>>>) = flip (.), с которым легче иметь дело, по типу:

f . g = g >>> f

g ::       a -> b
f ::            b -> c
g >>> f :: a ->      c

таким образом

flip . const = const >>> flip

const :: a1 -> (b1 ->     a1    )
flip ::        (a2 -> (b2 -> c2)) -> (b2 -> a2 -> c2)
const >>> flip 
     ::  a1 ->                        b2 -> a2 -> c2      -- where
--           b1 ~ a2,   a1 ~ b2 -> c2
     ::  (b2 -> c2) ->                b2 -> a2 -> c2

или flip . const :: (b -> c) -> b -> a -> c.GHCi говорит то же самое.

Из этого типа мы сразу видим, что (flip . const) f x z = f x.Действительно, (flip . const) f x z = flip (const f) x z = const f z x = f x.

Три урока, которые можно извлечь из этого:

  • типы ассоциируются справа, а функциональное приложение - слева, f x y z = (((f x) y) z), f :: a -> (b -> (c -> d));
  • помогает вертикальное выравнивание материала;
  • нумерация типовых переменных в отдельных типах помогает разделить их.
0 голосов
/ 10 мая 2018

Ну, здесь есть три функции:

  1. (.) :: (b -> c) -> (a -> b) -> a -> c;
  2. flip :: (a -> b -> c) -> b -> a -> c; и
  3. 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.

...