Let DD be the following type.
type DD = forall w. Comonad w => w A -> w BDD is isomorphic to simple A -> A -> B function.
This step shows DD is isomorphic to DD' below.
type DD = forall w. Comonad w => w A -> w B
type DD' = forall g. Functor g => Cofree g A -> g BUsing Yoneda lemma, w B is isomorphic to the following form
w B ≅ forall g. (Functor g) => (w ~> g) -> g B
---- (1)
where ~> denotes the type of natural transformations (which are not necessarily a comonad morphism).
Substituting (1) to DD:
DD
≅ forall w. Comonad w => w A -> forall g. Functor g => (w ~> g) -> g B
≅ forall w g. (Comonad w, Functor g) => w A -> (w ~> g) -> g B
---- (2)
By the universal property of the Cofree comonad, any natural transformation f :: w ~> g has one-to-one correspondence with Comonad morphism f' :: w ~~> Cofree g. Here, the longer wiggled arrow ~~> is used to denote the type of Comonad morphisms rather than mere natural transformation.
Using this isomorphism, DD can be transformed further:
DD
≅ forall w g. (Comonad w, Functor g) => w A -> (w ~~> Cofree g) -> g B
≅ forall g. Functor g =>
forall w. (Comonad w) => (w ~~> Cofree g) -> (w A -> g B)
≅ forall g. Functor g =>
forall w. (Comonad w) => (w ~~> Cofree g) -> (w A -> g B)
---- (3)
Regard both (w ~~> Cofree g) and (w A -> g B) as two contravariant functors from
the category of Comonads to Type, and forall w. (Comonad w) => (w ~~> Cofree g) -> (w A -> g B)
as the type of natural transformations between them.
Then, the (contravariant) Yoneda theorem says
(forall w. (Comonad w) => (w ~~> Cofree g) -> (w A -> g B))
≅ Cofree g A -> g B
therefore DD is isomorphic to the goal DD'.
DD
≅ forall g. Functor g =>
forall w. (Comonad w) => (w ~~> Cofree g) -> (w A -> g B)
≅ forall g. Functor g => Cofree g A -> g B
= DD'
(this step is more handwavy than Step1)
DD'
≅ forall g. Functor g => Cofree g A -> g B
≅ forall g. Functor g => (A, g (Cofree g A)) -> g B
≅ forall g. Functor g => (A, g (A, g (A, Cofree g A))) -> g B
≅ A -> forall g. Functor g => g (A, g (A, Cofree g A)) -> g B
-
To make a
g Bvalue fromga : g (A, g (...))value, one can only dofmap (f :: (A, g (...)) -> B) gasincegis only aFunctorand no value other thangain the environment provideg _value from nothing -
f :: (A, g (...)) -> Bcan not "use" the second argumentg (...), becausegis an opaqueFunctortype and also no way to "extract"(...)value out ofg. therefore,fmust bef = (f' :: A -> B) . fst -
Conversely, given
forall g. Functor g => g (A, g (A, Cofree g A)) -> g B, letg = (->) Aand passrec = \a -> (a :> rec) :: Cofree ((->) A)in, then getg B ~ A -> B. this is the right inverse off↦fmap (f . fst) :: g (A, g (A, Cofree g A)) -> g B
Thus
DD'
≅ A -> (A -> B)