Я попытался следовать статье Габриэля Гонсалеса и столкнулся с несоответствием типов . Рассмотрим следующий короткий модуль:
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE Rank2Types #-}
module Yoneda where
newtype F a = F a deriving (Show, Functor)
type G f a = forall a'. (a -> a') -> f a'
fw :: Functor f => G f a -> f a
fw x = x id
bw :: Functor f => f a -> G f a
bw x = \f -> fmap f x
Он компилируется нормально. (И с ghc
8.2.2 и с 8.4.3.) Но когда тыкаю в repl, fw
и bw
не сочиняются:
λ :t bw . fw
<interactive>:1:6: error:
• Couldn't match type ‘a’ with ‘G f a1’
‘a’ is a rigid type variable bound by
the inferred type of it :: Functor f => a -> (a1 -> a') -> f a'
at <interactive>:1:1
Expected type: a -> f a1
Actual type: G f a1 -> f a1
• In the second argument of ‘(.)’, namely ‘fw’
In the expression: bw . fw
Когда я смотрю на bw
более внимательно, оказывается, что типы функтора, которые он принимает и возвращает, различны:
λ :t bw
bw :: Functor f1 => f2 a1 -> (a2 -> a') -> f1 a'
— Хоть я и указал в подписи типа, что они должны быть одинаковыми! И какие бы аннотации типов я ни добавлял к fw
и bw
, они не хотят унифицироваться.
Если я уберу подпись типа из fw
, все будет работать гладко. В частности, предполагаемая сигнатура типа будет следующей:
fw :: ((a -> a) -> t) -> t
Итак, получается, что квантификатор forall
все портит. Но я не понимаю, почему. Разве это не должно означать "подойдет любой тип a -> a'
, включая a -> a
"? Кажется, что один и тот же синоним типа G f a
действует по-разному в сигнатурах типов fw
и bw
!
Что тут происходит?
Еще немного экспериментов:
λ (fw . bw) (F 1)
...error...
λ (fw (bw (F 1)))
F 1
λ :t fw . undefined
...error...
λ :t undefined . fw
...error
λ :t bw . undefined
bw . undefined :: Functor f => a1 -> (a2 -> a') -> f a'
λ :t undefined . bw
undefined . bw :: Functor f => f a -> c
Итак, (как указал @chi в ответе) никакая функция не может быть составлена из fw
. Но не так для bw
. Почему?
bw :: Functor f => f a -> (a -> a') -> f a'
. Как вы получилиf1
иf2
выше? - person chi   schedule 29.07.2018