module Numeric.Ring.Endomorphism
( End(..)
, toEnd
, fromEnd
, frobenius
) where
import Data.Monoid
import Numeric.Algebra
import Prelude hiding ((*),(+),(),negate,subtract)
import Data.Proxy
import Data.Semigroup (Semigroup((<>)))
newtype End a = End { appEnd :: a -> a }
instance Semigroup (End r) where
(End a) <> (End b) = End (a . b)
instance Monoid (End r) where
mappend (End a) (End b) = End (a . b)
mempty = End id
instance Additive r => Additive (End r) where
End f + End g = End (f + g)
instance Abelian r => Abelian (End r)
instance Monoidal r => Monoidal (End r) where
zero = End (const zero)
instance Group r => Group (End r) where
End f End g = End (f g)
negate (End f) = End (negate f)
subtract (End f) (End g) = End (subtract f g)
instance Multiplicative (End r) where
End f * End g = End (f . g)
instance Unital (End r) where
one = End id
instance (Abelian r, Commutative r) => Commutative (End r)
instance (Abelian r, Monoidal r) => Semiring (End r)
instance (Abelian r, Monoidal r) => Rig (End r)
instance (Abelian r, Group r) => Ring (End r)
instance (Monoidal m, Abelian m) => LeftModule (End m) (End m) where
End f .* End g = End (f . g)
instance (Monoidal m, Abelian m) => RightModule (End m) (End m) where
End f *. End g = End (f . g)
instance LeftModule r m => LeftModule r (End m) where
r .* End f = End (\e -> r .* f e)
instance RightModule r m => RightModule r (End m) where
End f *. r = End (\e -> f e *. r)
toEnd :: Multiplicative r => r -> End r
toEnd r = End (*r)
fromEnd :: Unital r => End r -> r
fromEnd (End f) = f one
frobenius :: Characteristic r => End r
frobenius = End $ \r -> r `pow` char (ofRing r)
ofRing :: r -> Proxy r
ofRing _ = Proxy