module Algebra (Semigroup (..), Monoid (mempty), Group (..), Abelian, Idempotent,
(+), (), (*), (/)) where
import Control.Category
import Data.Functor
import Data.Functor.Const
import Data.Functor.Identity
import Data.Monoid hiding ((<>))
import Data.Proxy
import Data.Semigroup
import Data.Word
import Numeric.Natural
import Prelude (Int, Integer)
import qualified Prelude as Base
class Semigroup a => Abelian a
instance Abelian ()
instance (Abelian a, Abelian b) => Abelian (a, b) where
instance (Abelian a, Abelian b, Abelian c) => Abelian (a, b, c) where
instance (Abelian a, Abelian b, Abelian c, Abelian d) => Abelian (a, b, c, d) where
instance (Abelian a, Abelian b, Abelian c, Abelian d, Abelian e) => Abelian (a, b, c, d, e) where
instance Abelian a => Abelian (Identity a)
instance Abelian a => Abelian (Dual a)
instance Abelian (Proxy a)
instance Abelian a => Abelian (Const a b)
instance Abelian b => Abelian (a -> b)
instance Abelian (Sum Natural)
instance Abelian (Sum Integer)
instance Abelian (Sum Word)
instance Abelian (Sum Int)
instance Abelian (Product Natural)
instance Abelian (Product Integer)
instance Abelian (Product Word)
instance Abelian (Product Int)
instance Abelian (Min Natural)
instance Abelian (Min Integer)
instance Abelian (Min Word)
instance Abelian (Min Int)
instance Abelian (Max Natural)
instance Abelian (Max Integer)
instance Abelian (Max Word)
instance Abelian (Max Int)
instance Abelian All
instance Abelian Any
class Semigroup a => Idempotent a
instance Idempotent ()
instance (Idempotent a, Idempotent b) => Idempotent (a, b) where
instance (Idempotent a, Idempotent b, Idempotent c) => Idempotent (a, b, c) where
instance (Idempotent a, Idempotent b, Idempotent c, Idempotent d) => Idempotent (a, b, c, d) where
instance (Idempotent a, Idempotent b, Idempotent c, Idempotent d, Idempotent e) => Idempotent (a, b, c, d, e) where
instance Idempotent a => Idempotent (Identity a)
instance Idempotent a => Idempotent (Dual a)
instance Idempotent (Proxy a)
instance Idempotent a => Idempotent (Const a b)
instance Idempotent b => Idempotent (a -> b)
instance Base.Ord a => Idempotent (Min a)
instance Base.Ord a => Idempotent (Max a)
class Monoid a => Group a where
invert :: a -> a
instance Group () where
invert () = ()
instance (Group a, Group b) => Group (a, b) where
invert (a, b) = (invert a, invert b)
instance (Group a, Group b, Group c) => Group (a, b, c) where
invert (a, b, c) = (invert a, invert b, invert c)
instance (Group a, Group b, Group c, Group d) => Group (a, b, c, d) where
invert (a, b, c, d) = (invert a, invert b, invert c, invert d)
instance (Group a, Group b, Group c, Group d, Group e) => Group (a, b, c, d, e) where
invert (a, b, c, d, e) = (invert a, invert b, invert c, invert d, invert e)
instance Group a => Group (Identity a) where invert = fmap invert
instance Group a => Group (Dual a) where invert (Dual a) = Dual (invert a)
instance Group (Proxy a) where invert Proxy = Proxy
instance Group a => Group (Const a b) where invert (Const a) = Const (invert a)
instance Group b => Group (a -> b) where invert = (.) invert
instance Group (Sum Integer) where invert (Sum a) = Sum (Base.negate a)
instance Group (Sum Int) where invert (Sum a) = Sum (Base.negate a)
instance Group (Sum Word) where invert (Sum a) = Sum (Base.negate a)
(+) :: Semigroup (Sum a) => a -> a -> a
a + b = getSum (Sum a <> Sum b)
() :: (Semigroup (Sum a), Group (Sum a)) => a -> a -> a
a b = getSum (Sum a <> invert (Sum b))
(*) :: Semigroup (Product a) => a -> a -> a
a * b = getProduct (Product a <> Product b)
(/) :: (Semigroup (Product a), Group (Product a)) => a -> a -> a
a / b = getProduct (Product a <> invert (Product b))