Сначала давайте перепишем это так, чтобы было понятно, какой аргумент соответствует какой части сигнатуры типа:
t2 :: (b1->b2) -> (b2->b1) -> p -> b1 -> b2
t2 x y z = x . y . x
z :: p
вообще не используется, поэтому мы можем легко устранить это, взглянув на
t3 :: (b1->b2) -> (b2->b1) -> b1 -> b2
t3 x y = x . y . x
Почему это тип? Что ж, цепочка композиций передает результат x
в y
, а результат y
обратно в x
. Другими словами, y
возвращает вас от типа результата x
обратно к типу аргумента x
. Поэтому тип y
должен быть «инвертированным» типом x
. Так
t3 :: (m->n) -> (n->m) -> ?
t3 x y = x . y . x
В типе композиции преобладают «внешние концы», то есть аргумент должен быть типом аргумента для x
, а результат должен быть типом результата ... опять же, x
. Следовательно
t3 :: (m->n) -> (n->m) -> m->n
t3 x y = x.y.x
Это то, что сказал вам GHCi с переименованными переменными типа.