Functor package:rebase

A type f is a Functor if it provides a function fmap which, given any types a and b lets you apply any function from (a -> b) to turn an f a into an f b, preserving the structure of f. Furthermore f needs to adhere to the following: Note, that the second law follows from the free theorem of the type fmap and the first law, so you need only check that the former condition holds. See https://www.schoolofhaskell.com/user/edwardk/snippets/fmap or https://github.com/quchen/articles/blob/master/second_functor_law.md for an explanation.
A Profunctor with the same input and output types can be seen as an Invariant functor.
Formally, the class Profunctor represents a profunctor from Hask -> Hask. Intuitively it is a bifunctor where the first argument is contravariant and the second argument is covariant. You can define a Profunctor by either defining dimap or by defining both lmap and rmap. If you supply dimap, you should ensure that:
dimap id idid
If you supply lmap and rmap, ensure:
lmap idid
rmap idid
If you supply both, you should also ensure:
dimap f g ≡ lmap f . rmap g
These ensure by parametricity:
dimap (f . g) (h . i) ≡ dimap g h . dimap f i
lmap (f . g) ≡ lmap g . lmap f
rmap (f . g) ≡ rmap f . rmap g
Laws:
unit . counitid
counit . unitid
ProfunctorFunctor has a polymorphic kind since 5.6.
Make a Functor over the second argument of a Bifunctor.
Wrap a Functor to be used as a member of Invariant.
Wrap a Profunctor to be used as a member of Invariant2.
Every Bifunctor is also an Invariant2 functor.
Every Profunctor is also an Invariant2 functor.
Every Functor is also an Invariant functor.
A Profunctor with the same input and output types can be seen as an Invariant functor.