Add an Endofunctor to the context of Functor (Covariant functor) and Contravariant
Motivation
There's a use case for a typeclass for codecs and probably other types which are both covariant and contravariant endofunctors. It is a typeclass like Profunctor but where the contravariant and covariant sides share the same type at all times (because it will have only one type parameter). For example a codec can be mapped so that it (de)serialises a different type.
Proposal
--|
-- specialisation of a profunctor where both left and right share the same type
-- a codec might be an instance of this because it is both covariant and contravariant
-- but a codec would be an instance of neither Functor nor Contravariant because their
-- map functions will always map one side to _|_
-- In a way this models the configuration of a mutation pipeline with tuning/continuations/routing depending
-- on the type.
--
-- It's in the context of Functor and Contravariant because endomap is fully defined for each
-- of them.
--
-- I can't think of what laws it might have apart from the below but I'm half convinced
-- this is an important typeclass.
--
-- I'm thinking things like:
-- @endomap f_retraction g_retraction . endomap f g@ is never extensionally inequal to id
-- (bottom not witnessing inequality), that is, f and f_retraction can be _|_ as well as total functions.
-- @endomap f g . endomap h i = endomap (f . h) (g . i)@
--
-- maybe someone can suggest something else?
--
-- Also important because it extends the landscape so we can mentally connect to things like sets of data items.
class Endofunctor f where
endomap :: (b -> a) -> (a -> b) -> f a -> f b
--|
-- Laws:
-- in addition to the existing laws
-- @endomap f g x = endomap h g x@, for all f and h
-- @endomap f g x = fmap g x@
-- @endomap undefined g x@ is no less defined than @endomap f g x@ for any f
class Endofunctor f => Functor f ...
--|
-- Laws:
-- in addition to the existing laws
-- @endomap f g x = endomap f h x@, for all g and h
-- @endomap f g x = contramap f x@
-- @endomap f undefined x@ is no less defined than @endomap f g x@ for any g
class Endofunctor f => Contravariant f ...
Please say if I should implement it and do a merge request.