{-# LANGUAGE UndecidableInstances #-}
module Algebra.Category.Endo where

import Prelude (Semigroup(..), Monoid(..))
import Algebra.Category
import Algebra.Classes

newtype Endo cat a = Endo (cat a a)

instance (Category cat, Obj cat a) => Semigroup (Endo cat a) where
  Endo cat a a
f <> :: Endo cat a -> Endo cat a -> Endo cat a
<> Endo cat a a
g = cat a a -> Endo cat a
forall (cat :: * -> * -> *) a. cat a a -> Endo cat a
Endo (cat a a
f cat a a -> cat a a -> cat a a
forall a b c.
(Obj cat a, Obj cat b, Obj cat c) =>
cat b c -> cat a b -> cat a c
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
(Category cat, Obj cat a, Obj cat b, Obj cat c) =>
cat b c -> cat a b -> cat a c
. cat a a
g)

instance (Category cat, Obj cat a) => Monoid (Endo cat a) where
  mempty :: Endo cat a
mempty = cat a a -> Endo cat a
forall (cat :: * -> * -> *) a. cat a a -> Endo cat a
Endo cat a a
forall a. Obj cat a => cat a a
forall k (cat :: k -> k -> *) (a :: k).
(Category cat, Obj cat a) =>
cat a a
id

instance (Category cat, Obj cat a) => Multiplicative (Endo cat a) where
  Endo cat a a
f * :: Endo cat a -> Endo cat a -> Endo cat a
* Endo cat a a
g = cat a a -> Endo cat a
forall (cat :: * -> * -> *) a. cat a a -> Endo cat a
Endo (cat a a
f cat a a -> cat a a -> cat a a
forall a b c.
(Obj cat a, Obj cat b, Obj cat c) =>
cat b c -> cat a b -> cat a c
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
(Category cat, Obj cat a, Obj cat b, Obj cat c) =>
cat b c -> cat a b -> cat a c
. cat a a
g)
  one :: Endo cat a
one = cat a a -> Endo cat a
forall (cat :: * -> * -> *) a. cat a a -> Endo cat a
Endo cat a a
forall a. Obj cat a => cat a a
forall k (cat :: k -> k -> *) (a :: k).
(Category cat, Obj cat a) =>
cat a a
id

instance (Dagger cat, Obj cat a) => Division (Endo cat a) where
  recip :: Endo cat a -> Endo cat a
recip (Endo cat a a
m) = cat a a -> Endo cat a
forall (cat :: * -> * -> *) a. cat a a -> Endo cat a
Endo (cat a a -> cat a a
forall a b. O2 cat a b => cat a b -> cat b a
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k).
(Dagger cat, O2 cat a b) =>
cat a b -> cat b a
dagger cat a a
m)