class Contravariant f where contramap :: (a -> b) -> f b -> f a -- The flipped internal hom functor newtype (:^:) a b = Hom { getHom :: b -> a} -- is contravariant in the second argument instance Contravariant ((:^:) a) where contramap f (Hom g) = Hom $ g . f -- and covariant in the first, which we'll try to express... -- This would be nice, but Haskell does not allow unsaturated type families :( {- type family Flip (f :: k -> i -> Type) (a :: i) (b :: k) :: Type where Flip f a b = f b a instance Functor (Flip @a @b (:^:) a b) where fmap f (Hom g) = Hom (f . g) -} -- so we have to resort to rather crude methods... newtype FHom b a = FHom (a :^: b) instance Functor (FHom b) where fmap f (FHom (Hom g)) = FHom $ Hom (f . g) instance Semigroup a => Semigroup (a :^: b) where (Hom f) <> (Hom g) = Hom $ \x -> f x <> g x instance Monoid a => Monoid (a :^: b) where mempty = Hom (const mempty)