module Pandora.Pattern.Functor.Divariant where

import Pandora.Pattern.Category ((.), ($))

infixl 4 >->

{- |
> When providing a new instance, you should ensure it satisfies the two laws:
> * Identity: dimap identity identity ≡ identity
> * Interpreted: dimap (f . g) (h . i) ≡ dimap g h . dimap f i
-}

class Divariant (v :: * -> * -> *) where
	{-# MINIMAL (>->) #-}
	(>->) :: v a b -> v c d -> v b c -> v a d
	-- | Prefix version of '>->'
	dimap :: v a b -> v c d -> v b c -> v a d
	dimap v a b
f v c d
g v b c
x = v a b
f v a b -> v c d -> v b c -> v a d
forall (v :: * -> * -> *) a b c d.
Divariant v =>
v a b -> v c d -> v b c -> v a d
>-> v c d
g (v b c -> v a d) -> v b c -> v a d
forall (m :: * -> * -> *) a b. Category m => m a b -> m a b
$ v b c
x

instance Divariant ((->)) where
	>-> :: (a -> b) -> (c -> d) -> (b -> c) -> a -> d
(>->) a -> b
ab c -> d
cd b -> c
bc = c -> d
cd (c -> d) -> (a -> c) -> a -> d
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. b -> c
bc (b -> c) -> (a -> b) -> a -> c
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. a -> b
ab