module Ideas.Common.Algebra.GroupLaws
(
associative, leftIdentity
, rightIdentity, identityLaws, monoidLaws, commutativeMonoidLaws
, idempotent
, leftInverse, rightInverse, doubleInverse
, inverseIdentity, inverseDistrFlipped, inverseLaws, groupLaws
, appendInverseLaws
, commutative, inverseDistr, abelianGroupLaws
, leftZero, rightZero, zeroLaws, monoidZeroLaws
, associativeFor, commutativeFor, idempotentFor
, leftDistributiveFor, rightDistributiveFor
) where
import Data.Monoid
import Ideas.Common.Algebra.Group
import Ideas.Common.Algebra.Law
associative :: Monoid a => Law a
associative = associativeFor (<>)
leftIdentity :: Monoid a => Law a
leftIdentity = law "left-identity" $ \a -> mempty <> a :==: a
rightIdentity :: Monoid a => Law a
rightIdentity = law "right-identity" $ \a -> a <> mempty :==: a
identityLaws :: Monoid a => [Law a]
identityLaws = [leftIdentity, rightIdentity]
monoidLaws :: Monoid a => [Law a]
monoidLaws = associative : identityLaws
commutativeMonoidLaws :: Monoid a => [Law a]
commutativeMonoidLaws = monoidLaws ++ [commutative]
idempotent :: Monoid a => Law a
idempotent = idempotentFor (<>)
leftInverse :: Group a => Law a
leftInverse = law "left-inverse" $ \a -> inverse a <> a :==: mempty
rightInverse :: Group a => Law a
rightInverse = law "right-inverse" $ \a -> a <> inverse a :==: mempty
doubleInverse :: Group a => Law a
doubleInverse = law "double-inverse" $ \a -> inverse (inverse a) :==: a
inverseIdentity :: Group a => Law a
inverseIdentity = law "inverse-identity" $ inverse mempty :==: mempty
inverseDistrFlipped :: Group a => Law a
inverseDistrFlipped = law "inverse-distr-flipped" $ \a b ->
inverse (a <> b) :==: inverse b <> inverse a
inverseLaws :: Group a => [Law a]
inverseLaws = [leftInverse, rightInverse]
groupLaws :: Group a => [Law a]
groupLaws = monoidLaws ++ inverseLaws ++
[doubleInverse, inverseIdentity, inverseDistrFlipped]
appendInverseLaws :: Group a => [Law a]
appendInverseLaws =
[ make 1 $ \a b -> a <>- b :==: a <> inverse b
, make 2 $ \a -> a <>- a :==: mempty
, make 3 $ \a -> a <>- mempty :==: a
, make 4 $ \a -> mempty <>- a :==: inverse a
, make 5 $ \a b c -> a <>- (b <> c) :==: (a <>- b) <>- c
, make 6 $ \a b c -> a <>- (b <>- c) :==: (a <>- b) <> c
, make 7 $ \a b c -> a <> (b <>- c) :==: (a <> b) <>- c
, make 8 $ \a b -> a <>- inverse b :==: a <> b
, make 9 $ \a b -> inverse (a <>- b) :==: inverse a <> b
]
where
make n = law ("append-inverse-law" ++ show (n :: Int))
commutative :: Monoid a => Law a
commutative = commutativeFor (<>)
inverseDistr :: Group a => Law a
inverseDistr = law "inverse-distr" $ \a b ->
inverse (a <> b) :==: (inverse a <> inverse b)
abelianGroupLaws :: Group a => [Law a]
abelianGroupLaws = groupLaws ++ [commutative, inverseDistr]
leftZero :: MonoidZero a => Law a
leftZero = law "left-zero" $ \a -> mzero <> a :==: mzero
rightZero:: MonoidZero a => Law a
rightZero = law "right-zero" $ \a -> a <> mzero :==: mzero
zeroLaws :: MonoidZero a => [Law a]
zeroLaws = [leftZero, rightZero]
monoidZeroLaws :: MonoidZero a => [Law a]
monoidZeroLaws = monoidLaws ++ zeroLaws
associativeFor :: (a -> a -> a) -> Law a
associativeFor (?) = law "associative" $ \a b c ->
a ? (b ? c) :==: (a ? b) ? c
commutativeFor :: (a -> a -> a) -> Law a
commutativeFor (?) = law "commutative" $ \a b -> a ? b :==: b ? a
idempotentFor :: (a -> a -> a) -> Law a
idempotentFor (?) = law "idempotent" $ \a -> a ? a :==: a
leftDistributiveFor :: (a -> a -> a) -> (a -> a -> a) -> Law a
leftDistributiveFor (<*>) (<+>) = law "left-distributive" $ \a b c ->
a <*> (b <+> c) :==: (a <*> b) <+> (a <*> c)
rightDistributiveFor :: (a -> a -> a) -> (a -> a -> a) -> Law a
rightDistributiveFor (<*>) (<+>) = law "right-distributive" $ \a b c ->
(a <+> b) <*> c :==: (a <*> c) <+> (b <*> c)