```{-# LANGUAGE NoImplicitPrelude #-}
{- * Class -}
C,
zero,
(+), (-),
negate, subtract,

{- * Complex functions -}
sum, sum1,

{- * Instances for atomic types -}
propAssociative,
propCommutative,
propIdentity,
propInverse,
) where

import qualified Algebra.Laws as Laws

import Data.Int  (Int,  Int8,  Int16,  Int32,  Int64,  )
import Data.Word (Word, Word8, Word16, Word32, Word64, )

import qualified Data.Ratio as Ratio98
import qualified Prelude as P
import Prelude(Int, Integer, Float, Double, fromInteger, )
import PreludeBase

infixl 6  +, -

{- |
Additive a encapsulates the notion of a commutative group, specified
by the following laws:

@
a + b === b + a
(a + b) + c === a + (b + c)
zero + a === a
a + negate a === 0
@

Typical examples include integers, dollars, and vectors.

Minimal definition: '+', 'zero', and ('negate' or '(-)')
-}

class C a where
-- | zero element of the vector space
zero     :: a
-- | add and subtract elements
(+), (-) :: a -> a -> a
-- | inverse with respect to '+'
negate   :: a -> a

{-# INLINE negate #-}
negate a = zero - a
{-# INLINE (-) #-}
a - b    = a + negate b

{- |
'subtract' is @(-)@ with swapped operand order.
This is the operand order which will be needed in most cases
of partial application.
-}
subtract :: C a => a -> a -> a
subtract = flip (-)

{- |
Sum up all elements of a list.
An empty list yields zero.
-}
sum :: (C a) => [a] -> a
sum = foldl (+) zero

{- |
Sum up all elements of a non-empty list.
This avoids including a zero which is useful for types
where no universal zero is available.
-}
sum1 :: (C a) => [a] -> a
sum1 = foldl1 (+)

{-* Instances for atomic types -}

instance C Integer where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Float   where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Double  where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Int     where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Int8    where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Int16   where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Int32   where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Int64   where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Word    where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Word8   where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Word16  where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Word32  where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

instance C Word64  where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero   = P.fromInteger 0
negate = P.negate
(+)    = (P.+)
(-)    = (P.-)

{-* Instances for composed types -}

instance (C v0, C v1) => C (v0, v1) where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero                   = (zero, zero)
(+)    (x0,x1) (y0,y1) = ((+) x0 y0, (+) x1 y1)
(-)    (x0,x1) (y0,y1) = ((-) x0 y0, (-) x1 y1)
negate (x0,x1)         = (negate x0, negate x1)

instance (C v0, C v1, C v2) => C (v0, v1, v2) where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero                         = (zero, zero, zero)
(+)    (x0,x1,x2) (y0,y1,y2) = ((+) x0 y0, (+) x1 y1, (+) x2 y2)
(-)    (x0,x1,x2) (y0,y1,y2) = ((-) x0 y0, (-) x1 y1, (-) x2 y2)
negate (x0,x1,x2)            = (negate x0, negate x1, negate x2)

instance (C v) => C [v] where
zero   = []
negate = map negate
(+) (x:xs) (y:ys) = (+) x y : (+) xs ys
(+) xs     []     = xs
(+) []     ys     = ys
(-) (x:xs) (y:ys) = (-) x y : (-) xs ys
(-) xs     []     = xs
(-) []     ys     = negate ys

instance (C v) => C (b -> v) where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero       _ = zero
(+)    f g x = (+) (f x) (g x)
(-)    f g x = (-) (f x) (g x)
negate f   x = negate (f x)

{- * Properties -}

propAssociative :: (Eq a, C a) => a -> a -> a -> Bool
propCommutative :: (Eq a, C a) => a -> a -> Bool
propIdentity    :: (Eq a, C a) => a -> Bool
propInverse     :: (Eq a, C a) => a -> Bool

propCommutative  =  Laws.commutative (+)
propAssociative  =  Laws.associative (+)
propIdentity     =  Laws.identity (+) zero
propInverse      =  Laws.inverse (+) negate zero

-- legacy

instance (P.Integral a) => C (Ratio98.Ratio a) where
{-# INLINE zero #-}
{-# INLINE negate #-}
{-# INLINE (+) #-}
{-# INLINE (-) #-}
zero                =  0
(+)                 =  (P.+)
(-)                 =  (P.-)
negate              =  P.negate
```