module Pandora.Paradigm.Primary.Functor.Endo where

import Pandora.Pattern.Category (identity, (.))
import Pandora.Pattern.Functor.Invariant (Invariant (invmap))
import Pandora.Pattern.Object.Semigroup (Semigroup ((+)))
import Pandora.Pattern.Object.Monoid (Monoid (zero))

newtype Endo a = Endo { Endo a -> a -> a
endo :: a -> a }

instance Invariant Endo where
	invmap :: (a -> b) -> (b -> a) -> Endo a -> Endo b
invmap a -> b
f b -> a
g (Endo a -> a
x) = (b -> b) -> Endo b
forall a. (a -> a) -> Endo a
Endo (a -> b
f (a -> b) -> (b -> a) -> b -> b
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. a -> a
x (a -> a) -> (b -> a) -> b -> a
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. b -> a
g)

instance Semigroup (Endo a) where
	Endo a -> a
f + :: Endo a -> Endo a -> Endo a
+ Endo a -> a
g = (a -> a) -> Endo a
forall a. (a -> a) -> Endo a
Endo (a -> a
g (a -> a) -> (a -> a) -> a -> a
forall (m :: * -> * -> *) b c a.
Category m =>
m b c -> m a b -> m a c
. a -> a
f)

instance Monoid (Endo a) where
	zero :: Endo a
zero = (a -> a) -> Endo a
forall a. (a -> a) -> Endo a
Endo a -> a
forall (m :: * -> * -> *) a. Category m => m a a
identity