module Data.Algebra.Group where
import Control.Applicative
import qualified Data.Map as M
import qualified Data.IntMap as IM
import Data.Ratio
type Poly = []
infixr 4 ^+^
infixr 4 ^-^
class Group g where
zero :: g
(^+^) :: g -> g -> g
(^-^) :: g -> g -> g
neg :: g -> g
a ^+^ b = a ^-^ neg b
a ^-^ b = a ^+^ neg b
neg a = zero ^-^ a
instance Group Bool where
zero = False
(^+^) = (/=)
(^-^) = (/=)
neg = id
instance Group Int where
zero = 0
(^+^) = (+)
(^-^) = ()
neg = negate
instance Group Integer where
zero = 0
(^+^) = (+)
(^-^) = ()
neg = negate
instance Group Double where
zero = 0
(^+^) = (+)
(^-^) = ()
neg = negate
instance Integral a => Group (Ratio a) where
zero = 0
(^+^) = (+)
(^-^) = ()
neg = negate
instance Group g => Group (a -> g) where
zero = const zero
(^+^) = liftA2 (^+^)
(^-^) = liftA2 (^-^)
neg = fmap neg
instance (Ord k, Group g) => Group (M.Map k g) where
zero = M.empty
(^+^) = M.unionWith (^+^)
neg = fmap neg
instance Group g => Group (IM.IntMap g) where
zero = IM.empty
(^+^) = IM.unionWith (^+^)
neg = fmap neg
instance Group g => Group (Poly g) where
zero = []
[] ^+^ p = p
p ^+^ [] = p
(a:as) ^+^ (b:bs) = (a ^+^ b):(as ^+^ bs)
instance (Group g1, Group g2) => Group (g1, g2) where
zero = (zero, zero)
(x1, y1) ^+^ (x2, y2) = (x1 ^+^ x2, y1 ^+^ y2)
(x1, y1) ^-^ (x2, y2) = (x1 ^-^ x2, y1 ^-^ y2)
neg (x, y) = (neg x, neg y)
instance (Group g1, Group g2, Group g3) => Group (g1, g2, g3) where
zero = (zero, zero, zero)
(x1, y1, z1) ^+^ (x2, y2, z2) = (x1 ^+^ x2, y1 ^+^ y2, z1 ^+^ z2)
(x1, y1, z1) ^-^ (x2, y2, z2) = (x1 ^-^ x2, y1 ^-^ y2, z1 ^-^ z2)
neg (x, y, z) = (neg x, neg y, neg z)
instance (Group g1, Group g2, Group g3, Group g4) => Group (g1, g2, g3, g4) where
zero = (zero, zero, zero, zero)
(x1, y1, z1, w1) ^+^ (x2, y2, z2, w2) = (x1 ^+^ x2, y1 ^+^ y2, z1 ^+^ z2, w1 ^+^ w2)
(x1, y1, z1, w1) ^-^ (x2, y2, z2, w2) = (x1 ^-^ x2, y1 ^-^ y2, z1 ^-^ z2, w1 ^-^ w2)
neg (x, y, z, w) = (neg x, neg y, neg z, neg w)
gsum :: Group g => [g] -> g
gsum = foldr (^+^) zero