module Pandora.Paradigm.Basis.Product (Product (..), type (:*), delta, swap, attached) where import Pandora.Core.Morphism (($)) import Pandora.Pattern.Functor.Covariant (Covariant ((<$>))) import Pandora.Pattern.Functor.Extractable (Extractable (extract)) import Pandora.Pattern.Functor.Extendable (Extendable ((=>>))) import Pandora.Pattern.Functor.Comonad (Comonad) import Pandora.Pattern.Functor.Adjoint (Adjoint (phi, psi)) import Pandora.Pattern.Object.Setoid (Setoid ((==)), (&&)) import Pandora.Pattern.Object.Semigroup (Semigroup ((<>))) import Pandora.Pattern.Object.Monoid (Monoid (unit)) import Pandora.Pattern.Object.Ringoid (Ringoid ((><))) import Pandora.Pattern.Object.Semilattice (Infimum ((/\)), Supremum ((\/))) import Pandora.Pattern.Object.Lattice (Lattice) import Pandora.Pattern.Object.Group (Group (inverse)) infixr 1 :* data Product a b = a :* b type (:*) = Product instance Covariant (Product a) where f <$> (x :* y) = x :* f y instance Extractable (Product a) where extract (x :* y) = y instance Extendable (Product a) where (x :* y) =>> f = (:*) x $ f (x :* y) instance Comonad (Product a) where instance Adjoint (Product a) ((->) a) where phi f x y = f $ y :* x psi f (y :* x) = f x y instance (Setoid a, Setoid b) => Setoid (Product a b) where (x :* y) == (x' :* y') = x == x' && y == y' instance (Semigroup a, Semigroup b) => Semigroup (Product a b) where (x :* y) <> (x' :* y') = x <> x' :* y <> y' instance (Monoid a, Monoid b) => Monoid (Product a b) where unit = unit :* unit instance (Ringoid a, Ringoid b) => Ringoid (Product a b) where (x :* y) >< (x' :* y') = x >< x' :* y >< y' instance (Infimum a, Infimum b) => Infimum (Product a b) where (x :* y) /\ (x' :* y') = x /\ x' :* y /\ y' instance (Supremum a, Supremum b) => Supremum (Product a b) where (x :* y) \/ (x' :* y') = x \/ x' :* y \/ y' instance (Lattice a, Lattice b) => Lattice (Product a b) where instance (Group a, Group b) => Group (Product a b) where inverse (x :* y) = inverse x :* inverse y delta :: a -> a :* a delta x = x :* x swap :: a :* b -> b :* a swap (x :* y) = y :* x attached :: a :* b -> a attached (x :* y) = x