phantom
is defined as:
phantom :: (Functor f, Contravariant f) => f a -> f b
phantom = contramap (const ()) . fmap (const ())
By parametricity on phantom
, we have:
fmap k . phantom = phantom . fmap h
In particular, for k = id
, we have (equation #1):
phantom = phantom . fmap h
Now consider:
bar :: (Functor f, Contravariant f) => (a -> x) -> f a -> f a
bar f = contramap f . fmap f
By parametricity:
h' . f = f' . h => fmap h . bar f = bar f' . fmap h
In particular, for f = id
, h = id
and h' = f'
, we have (equation #2):
id = bar f'
Next, let's specialise phantom
to:
endoPhantom :: (Functor f, Contravariant f) => f a -> f a
endoPhantom = phantom
endoPhantom = contramap (const ()) . fmap (const ())
, and, given the specialisation, the two const ()
are the same here. Therefore:
endoPhantom = bar (const ())
By equation #2:
endoPhantom = id
Finally, by equation #1:
phantom = endoPhantom . fmap h
phantom = fmap h