{-# LANGUAGE RebindableSyntax #-}
module Algebra.Additive (
    -- * Class
    C,
    zero,
    (+), (-),
    negate, subtract,

    -- * Complex functions
    sum, sum1,
    sumNestedAssociative,
    sumNestedCommutative,

    -- * Instance definition helpers
    elementAdd, elementSub, elementNeg,
    (<*>.+), (<*>.-), (<*>.-$),

    -- * 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 NumericPrelude.Elementwise as Elem
import Control.Applicative (Applicative(pure, (<*>)), )
import Data.Tuple.HT (fst3, snd3, thd3, )
import qualified Data.List.Match as Match

import qualified Data.Complex as Complex98
import qualified Data.Ratio as Ratio98
import qualified Prelude as P
import Prelude (Integer, Float, Double, fromInteger, )
import NumericPrelude.Base


{- $setup
>>> import qualified Algebra.Additive as A
>>> import qualified Test.QuickCheck as QC
-}


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
    {-# MINIMAL zero, (+), ((-) | negate) #-}
    -- | 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
a = a
forall a. C a => a
zero a -> a -> a
forall a. C a => a -> a -> a
- a
a
    {-# INLINE (-) #-}
    a
a - a
b    = a
a a -> a -> a
forall a. C a => a -> a -> a
+ a -> a
forall a. C a => a -> a
negate a
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 :: a -> a -> a
subtract = (a -> a -> a) -> a -> a -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (-)




{- |
Sum up all elements of a list.
An empty list yields zero.

This function is inappropriate for number types like Peano.
Maybe we should make 'sum' a method of Additive.
This would also make 'lengthLeft' and 'lengthRight' superfluous.
-}
sum :: (C a) => [a] -> a
sum :: [a] -> a
sum = (a -> a -> a) -> a -> [a] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl a -> a -> a
forall a. C a => a -> a -> a
(+) a
forall a. C a => a
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.
ToDo: Should have NonEmpty type.

prop> \(QC.NonEmpty ns) -> A.sum ns == (A.sum1 ns :: Integer)
-}
sum1 :: (C a) => [a] -> a
sum1 :: [a] -> a
sum1 = (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 a -> a -> a
forall a. C a => a -> a -> a
(+)


{- |
Sum the operands in an order,
such that the dependencies are minimized.
Does this have a measurably effect on speed?

Requires associativity.

prop> \ns -> A.sum ns == (A.sumNestedAssociative ns :: Integer)
-}
sumNestedAssociative :: (C a) => [a] -> a
sumNestedAssociative :: [a] -> a
sumNestedAssociative [] = a
forall a. C a => a
zero
sumNestedAssociative [a
x] = a
x
sumNestedAssociative [a]
xs = [a] -> a
forall a. C a => [a] -> a
sumNestedAssociative ([a] -> [a]
forall a. C a => [a] -> [a]
sum2 [a]
xs)

{- |
Make sure that the last entries in the list
are equally often part of an addition.
Maybe this can reduce rounding errors.
The list that sum2 computes is a breadth-first-flattened binary tree.

Requires associativity and commutativity.

prop> \ns -> A.sum ns == (A.sumNestedCommutative ns :: Integer)
-}
sumNestedCommutative :: (C a) => [a] -> a
sumNestedCommutative :: [a] -> a
sumNestedCommutative [] = a
forall a. C a => a
zero
sumNestedCommutative xs :: [a]
xs@(a
_:[a]
rs) =
   let ys :: [a]
ys = [a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a] -> [a] -> [a]
forall b a. [b] -> [a] -> [a]
Match.take [a]
rs ([a] -> [a]
forall a. C a => [a] -> [a]
sum2 [a]
ys)
   in  [a] -> a
forall a. [a] -> a
last [a]
ys

_sumNestedCommutative :: (C a) => [a] -> a
_sumNestedCommutative :: [a] -> a
_sumNestedCommutative [] = a
forall a. C a => a
zero
_sumNestedCommutative xs :: [a]
xs@(a
_:[a]
rs) =
   let ys :: [a]
ys = [a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
rs) ([a] -> [a]
forall a. C a => [a] -> [a]
sum2 [a]
ys)
   in  [a] -> a
forall a. [a] -> a
last [a]
ys

{-
[a,b,c, a+b,c+(a+b)]
[a,b,c,d, a+b,c+d,(a+b)+(c+d)]
[a,b,c,d,e, a+b,c+d,e+(a+b),(c+d)+e+(a+b)]
[a,b,c,d,e,f, a+b,c+d,e+f,(a+b)+(c+d),(e+f)+((a+b)+(c+d))]
-}

sum2 :: (C a) => [a] -> [a]
sum2 :: [a] -> [a]
sum2 (a
x:a
y:[a]
rest) = (a
xa -> a -> a
forall a. C a => a -> a -> a
+a
y) a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a]
forall a. C a => [a] -> [a]
sum2 [a]
rest
sum2 [a]
xs = [a]
xs



{- |
Instead of baking the add operation into the element function,
we could use higher rank types
and pass a generic @uncurry (+)@ to the run function.
We do not do so in order to stay Haskell 98
at least for parts of NumericPrelude.
-}
{-# INLINE elementAdd #-}
elementAdd ::
   (C x) =>
   (v -> x) -> Elem.T (v,v) x
elementAdd :: (v -> x) -> T (v, v) x
elementAdd v -> x
f =
   ((v, v) -> x) -> T (v, v) x
forall v a. (v -> a) -> T v a
Elem.element (\(v
x,v
y) -> v -> x
f v
x x -> x -> x
forall a. C a => a -> a -> a
+ v -> x
f v
y)

{-# INLINE elementSub #-}
elementSub ::
   (C x) =>
   (v -> x) -> Elem.T (v,v) x
elementSub :: (v -> x) -> T (v, v) x
elementSub v -> x
f =
   ((v, v) -> x) -> T (v, v) x
forall v a. (v -> a) -> T v a
Elem.element (\(v
x,v
y) -> v -> x
f v
x x -> x -> x
forall a. C a => a -> a -> a
- v -> x
f v
y)

{-# INLINE elementNeg #-}
elementNeg ::
   (C x) =>
   (v -> x) -> Elem.T v x
elementNeg :: (v -> x) -> T v x
elementNeg v -> x
f =
   (v -> x) -> T v x
forall v a. (v -> a) -> T v a
Elem.element (x -> x
forall a. C a => a -> a
negate (x -> x) -> (v -> x) -> v -> x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v -> x
f)


-- like <*>
infixl 4 <*>.+, <*>.-, <*>.-$

{- |
> addPair :: (Additive.C a, Additive.C b) => (a,b) -> (a,b) -> (a,b)
> addPair = Elem.run2 $ Elem.with (,) <*>.+  fst <*>.+  snd
-}
{-# INLINE (<*>.+) #-}
(<*>.+) ::
   (C x) =>
   Elem.T (v,v) (x -> a) -> (v -> x) -> Elem.T (v,v) a
<*>.+ :: T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
(<*>.+) T (v, v) (x -> a)
f v -> x
acc =
   T (v, v) (x -> a)
f T (v, v) (x -> a) -> T (v, v) x -> T (v, v) a
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (v -> x) -> T (v, v) x
forall x v. C x => (v -> x) -> T (v, v) x
elementAdd v -> x
acc

{-# INLINE (<*>.-) #-}
(<*>.-) ::
   (C x) =>
   Elem.T (v,v) (x -> a) -> (v -> x) -> Elem.T (v,v) a
<*>.- :: T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
(<*>.-) T (v, v) (x -> a)
f v -> x
acc =
   T (v, v) (x -> a)
f T (v, v) (x -> a) -> T (v, v) x -> T (v, v) a
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (v -> x) -> T (v, v) x
forall x v. C x => (v -> x) -> T (v, v) x
elementSub v -> x
acc

{-# INLINE (<*>.-$) #-}
(<*>.-$) ::
   (C x) =>
   Elem.T v (x -> a) -> (v -> x) -> Elem.T v a
<*>.-$ :: T v (x -> a) -> (v -> x) -> T v a
(<*>.-$) T v (x -> a)
f v -> x
acc =
   T v (x -> a)
f T v (x -> a) -> T v x -> T v a
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (v -> x) -> T v x
forall x v. C x => (v -> x) -> T v x
elementNeg v -> x
acc


-- * Instances for atomic types

instance C Integer where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Integer
zero   = Integer -> Integer
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Integer -> Integer
negate = Integer -> Integer
forall a. Num a => a -> a
P.negate
   + :: Integer -> Integer -> Integer
(+)    = Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(P.-)

instance C Float   where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Float
zero   = Integer -> Float
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Float -> Float
negate = Float -> Float
forall a. Num a => a -> a
P.negate
   + :: Float -> Float -> Float
(+)    = Float -> Float -> Float
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Float -> Float -> Float
forall a. Num a => a -> a -> a
(P.-)

instance C Double  where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Double
zero   = Integer -> Double
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Double -> Double
negate = Double -> Double
forall a. Num a => a -> a
P.negate
   + :: Double -> Double -> Double
(+)    = Double -> Double -> Double
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Double -> Double -> Double
forall a. Num a => a -> a -> a
(P.-)


instance C Int     where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Int
zero   = Integer -> Int
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Int -> Int
negate = Int -> Int
forall a. Num a => a -> a
P.negate
   + :: Int -> Int -> Int
(+)    = Int -> Int -> Int
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Int -> Int -> Int
forall a. Num a => a -> a -> a
(P.-)

instance C Int8    where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Int8
zero   = Integer -> Int8
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Int8 -> Int8
negate = Int8 -> Int8
forall a. Num a => a -> a
P.negate
   + :: Int8 -> Int8 -> Int8
(+)    = Int8 -> Int8 -> Int8
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Int8 -> Int8 -> Int8
forall a. Num a => a -> a -> a
(P.-)

instance C Int16   where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Int16
zero   = Integer -> Int16
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Int16 -> Int16
negate = Int16 -> Int16
forall a. Num a => a -> a
P.negate
   + :: Int16 -> Int16 -> Int16
(+)    = Int16 -> Int16 -> Int16
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Int16 -> Int16 -> Int16
forall a. Num a => a -> a -> a
(P.-)

instance C Int32   where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Int32
zero   = Integer -> Int32
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Int32 -> Int32
negate = Int32 -> Int32
forall a. Num a => a -> a
P.negate
   + :: Int32 -> Int32 -> Int32
(+)    = Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
(P.-)

instance C Int64   where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Int64
zero   = Integer -> Int64
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Int64 -> Int64
negate = Int64 -> Int64
forall a. Num a => a -> a
P.negate
   + :: Int64 -> Int64 -> Int64
(+)    = Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
(P.-)


instance C Word    where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Word
zero   = Integer -> Word
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Word -> Word
negate = Word -> Word
forall a. Num a => a -> a
P.negate
   + :: Word -> Word -> Word
(+)    = Word -> Word -> Word
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Word -> Word -> Word
forall a. Num a => a -> a -> a
(P.-)

instance C Word8   where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Word8
zero   = Integer -> Word8
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Word8 -> Word8
negate = Word8 -> Word8
forall a. Num a => a -> a
P.negate
   + :: Word8 -> Word8 -> Word8
(+)    = Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
(P.-)

instance C Word16  where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Word16
zero   = Integer -> Word16
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Word16 -> Word16
negate = Word16 -> Word16
forall a. Num a => a -> a
P.negate
   + :: Word16 -> Word16 -> Word16
(+)    = Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
(P.-)

instance C Word32  where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Word32
zero   = Integer -> Word32
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Word32 -> Word32
negate = Word32 -> Word32
forall a. Num a => a -> a
P.negate
   + :: Word32 -> Word32 -> Word32
(+)    = Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
(P.-)

instance C Word64  where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Word64
zero   = Integer -> Word64
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   negate :: Word64 -> Word64
negate = Word64 -> Word64
forall a. Num a => a -> a
P.negate
   + :: Word64 -> Word64 -> Word64
(+)    = Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
(P.+)
   (-)    = Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
(P.-)




-- * Instances for composed types

instance (C v0, C v1) => C (v0, v1) where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: (v0, v1)
zero   = (,) v0
forall a. C a => a
zero v1
forall a. C a => a
zero
   + :: (v0, v1) -> (v0, v1) -> (v0, v1)
(+)    = T ((v0, v1), (v0, v1)) (v0, v1) -> (v0, v1) -> (v0, v1) -> (v0, v1)
forall x y a. T (x, y) a -> x -> y -> a
Elem.run2 (T ((v0, v1), (v0, v1)) (v0, v1)
 -> (v0, v1) -> (v0, v1) -> (v0, v1))
-> T ((v0, v1), (v0, v1)) (v0, v1)
-> (v0, v1)
-> (v0, v1)
-> (v0, v1)
forall a b. (a -> b) -> a -> b
$ (v0 -> v1 -> (v0, v1))
-> T ((v0, v1), (v0, v1)) (v0 -> v1 -> (v0, v1))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,) T ((v0, v1), (v0, v1)) (v0 -> v1 -> (v0, v1))
-> ((v0, v1) -> v0) -> T ((v0, v1), (v0, v1)) (v1 -> (v0, v1))
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.+  (v0, v1) -> v0
forall a b. (a, b) -> a
fst T ((v0, v1), (v0, v1)) (v1 -> (v0, v1))
-> ((v0, v1) -> v1) -> T ((v0, v1), (v0, v1)) (v0, v1)
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.+  (v0, v1) -> v1
forall a b. (a, b) -> b
snd
   (-)    = T ((v0, v1), (v0, v1)) (v0, v1) -> (v0, v1) -> (v0, v1) -> (v0, v1)
forall x y a. T (x, y) a -> x -> y -> a
Elem.run2 (T ((v0, v1), (v0, v1)) (v0, v1)
 -> (v0, v1) -> (v0, v1) -> (v0, v1))
-> T ((v0, v1), (v0, v1)) (v0, v1)
-> (v0, v1)
-> (v0, v1)
-> (v0, v1)
forall a b. (a -> b) -> a -> b
$ (v0 -> v1 -> (v0, v1))
-> T ((v0, v1), (v0, v1)) (v0 -> v1 -> (v0, v1))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,) T ((v0, v1), (v0, v1)) (v0 -> v1 -> (v0, v1))
-> ((v0, v1) -> v0) -> T ((v0, v1), (v0, v1)) (v1 -> (v0, v1))
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.-  (v0, v1) -> v0
forall a b. (a, b) -> a
fst T ((v0, v1), (v0, v1)) (v1 -> (v0, v1))
-> ((v0, v1) -> v1) -> T ((v0, v1), (v0, v1)) (v0, v1)
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.-  (v0, v1) -> v1
forall a b. (a, b) -> b
snd
   negate :: (v0, v1) -> (v0, v1)
negate = T (v0, v1) (v0, v1) -> (v0, v1) -> (v0, v1)
forall v a. T v a -> v -> a
Elem.run  (T (v0, v1) (v0, v1) -> (v0, v1) -> (v0, v1))
-> T (v0, v1) (v0, v1) -> (v0, v1) -> (v0, v1)
forall a b. (a -> b) -> a -> b
$ (v0 -> v1 -> (v0, v1)) -> T (v0, v1) (v0 -> v1 -> (v0, v1))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,) T (v0, v1) (v0 -> v1 -> (v0, v1))
-> ((v0, v1) -> v0) -> T (v0, v1) (v1 -> (v0, v1))
forall x v a. C x => T v (x -> a) -> (v -> x) -> T v a
<*>.-$ (v0, v1) -> v0
forall a b. (a, b) -> a
fst T (v0, v1) (v1 -> (v0, v1))
-> ((v0, v1) -> v1) -> T (v0, v1) (v0, v1)
forall x v a. C x => T v (x -> a) -> (v -> x) -> T v a
<*>.-$ (v0, v1) -> v1
forall a b. (a, b) -> b
snd

instance (C v0, C v1, C v2) => C (v0, v1, v2) where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: (v0, v1, v2)
zero   = (,,) v0
forall a. C a => a
zero v1
forall a. C a => a
zero v2
forall a. C a => a
zero
   + :: (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2)
(+)    = T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
-> (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2)
forall x y a. T (x, y) a -> x -> y -> a
Elem.run2 (T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
 -> (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2))
-> T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
-> (v0, v1, v2)
-> (v0, v1, v2)
-> (v0, v1, v2)
forall a b. (a -> b) -> a -> b
$ (v0 -> v1 -> v2 -> (v0, v1, v2))
-> T ((v0, v1, v2), (v0, v1, v2)) (v0 -> v1 -> v2 -> (v0, v1, v2))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,,) T ((v0, v1, v2), (v0, v1, v2)) (v0 -> v1 -> v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v0)
-> T ((v0, v1, v2), (v0, v1, v2)) (v1 -> v2 -> (v0, v1, v2))
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.+  (v0, v1, v2) -> v0
forall a b c. (a, b, c) -> a
fst3 T ((v0, v1, v2), (v0, v1, v2)) (v1 -> v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v1)
-> T ((v0, v1, v2), (v0, v1, v2)) (v2 -> (v0, v1, v2))
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.+  (v0, v1, v2) -> v1
forall a b c. (a, b, c) -> b
snd3 T ((v0, v1, v2), (v0, v1, v2)) (v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v2)
-> T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.+  (v0, v1, v2) -> v2
forall a b c. (a, b, c) -> c
thd3
   (-)    = T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
-> (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2)
forall x y a. T (x, y) a -> x -> y -> a
Elem.run2 (T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
 -> (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2))
-> T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
-> (v0, v1, v2)
-> (v0, v1, v2)
-> (v0, v1, v2)
forall a b. (a -> b) -> a -> b
$ (v0 -> v1 -> v2 -> (v0, v1, v2))
-> T ((v0, v1, v2), (v0, v1, v2)) (v0 -> v1 -> v2 -> (v0, v1, v2))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,,) T ((v0, v1, v2), (v0, v1, v2)) (v0 -> v1 -> v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v0)
-> T ((v0, v1, v2), (v0, v1, v2)) (v1 -> v2 -> (v0, v1, v2))
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.-  (v0, v1, v2) -> v0
forall a b c. (a, b, c) -> a
fst3 T ((v0, v1, v2), (v0, v1, v2)) (v1 -> v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v1)
-> T ((v0, v1, v2), (v0, v1, v2)) (v2 -> (v0, v1, v2))
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.-  (v0, v1, v2) -> v1
forall a b c. (a, b, c) -> b
snd3 T ((v0, v1, v2), (v0, v1, v2)) (v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v2)
-> T ((v0, v1, v2), (v0, v1, v2)) (v0, v1, v2)
forall x v a. C x => T (v, v) (x -> a) -> (v -> x) -> T (v, v) a
<*>.-  (v0, v1, v2) -> v2
forall a b c. (a, b, c) -> c
thd3
   negate :: (v0, v1, v2) -> (v0, v1, v2)
negate = T (v0, v1, v2) (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2)
forall v a. T v a -> v -> a
Elem.run  (T (v0, v1, v2) (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2))
-> T (v0, v1, v2) (v0, v1, v2) -> (v0, v1, v2) -> (v0, v1, v2)
forall a b. (a -> b) -> a -> b
$ (v0 -> v1 -> v2 -> (v0, v1, v2))
-> T (v0, v1, v2) (v0 -> v1 -> v2 -> (v0, v1, v2))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,,) T (v0, v1, v2) (v0 -> v1 -> v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v0)
-> T (v0, v1, v2) (v1 -> v2 -> (v0, v1, v2))
forall x v a. C x => T v (x -> a) -> (v -> x) -> T v a
<*>.-$ (v0, v1, v2) -> v0
forall a b c. (a, b, c) -> a
fst3 T (v0, v1, v2) (v1 -> v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v1) -> T (v0, v1, v2) (v2 -> (v0, v1, v2))
forall x v a. C x => T v (x -> a) -> (v -> x) -> T v a
<*>.-$ (v0, v1, v2) -> v1
forall a b c. (a, b, c) -> b
snd3 T (v0, v1, v2) (v2 -> (v0, v1, v2))
-> ((v0, v1, v2) -> v2) -> T (v0, v1, v2) (v0, v1, v2)
forall x v a. C x => T v (x -> a) -> (v -> x) -> T v a
<*>.-$ (v0, v1, v2) -> v2
forall a b c. (a, b, c) -> c
thd3


{- |
The 'Additive' instantiations treat lists
as prefixes of infinite lists with zero filled tail.
This interpretation is not always appropriate.
The end of a list may just mean: End of available data.
In this case the shortening 'zip' semantics would be more appropriate.
-}
instance (C v) => C [v] where
   zero :: [v]
zero   = []
   negate :: [v] -> [v]
negate = (v -> v) -> [v] -> [v]
forall a b. (a -> b) -> [a] -> [b]
map v -> v
forall a. C a => a -> a
negate
   + :: [v] -> [v] -> [v]
(+) (v
x:[v]
xs) (v
y:[v]
ys) = v -> v -> v
forall a. C a => a -> a -> a
(+) v
x v
y v -> [v] -> [v]
forall a. a -> [a] -> [a]
: [v] -> [v] -> [v]
forall a. C a => a -> a -> a
(+) [v]
xs [v]
ys
   (+) [v]
xs     []     = [v]
xs
   (+) []     [v]
ys     = [v]
ys
   (-) (v
x:[v]
xs) (v
y:[v]
ys) = (-) v
x v
y v -> [v] -> [v]
forall a. a -> [a] -> [a]
: (-) [v]
xs [v]
ys
   (-) [v]
xs     []     = [v]
xs
   (-) []     [v]
ys     = [v] -> [v]
forall a. C a => a -> a
negate [v]
ys


instance (C v) => C (b -> v) where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: b -> v
zero       b
_ = v
forall a. C a => a
zero
   + :: (b -> v) -> (b -> v) -> b -> v
(+)    b -> v
f b -> v
g b
x = v -> v -> v
forall a. C a => a -> a -> a
(+) (b -> v
f b
x) (b -> v
g b
x)
   (-)    b -> v
f b -> v
g b
x = (-) (b -> v
f b
x) (b -> v
g b
x)
   negate :: (b -> v) -> b -> v
negate b -> v
f   b
x = v -> v
forall a. C a => a -> a
negate (b -> v
f b
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 :: a -> a -> Bool
propCommutative  =  (a -> a -> a) -> a -> a -> Bool
forall a b. Eq a => (b -> b -> a) -> b -> b -> Bool
Laws.commutative a -> a -> a
forall a. C a => a -> a -> a
(+)
propAssociative :: a -> a -> a -> Bool
propAssociative  =  (a -> a -> a) -> a -> a -> a -> Bool
forall a. Eq a => (a -> a -> a) -> a -> a -> a -> Bool
Laws.associative a -> a -> a
forall a. C a => a -> a -> a
(+)
propIdentity :: a -> Bool
propIdentity     =  (a -> a -> a) -> a -> a -> Bool
forall a. Eq a => (a -> a -> a) -> a -> a -> Bool
Laws.identity a -> a -> a
forall a. C a => a -> a -> a
(+) a
forall a. C a => a
zero
propInverse :: a -> Bool
propInverse      =  (a -> a -> a) -> (a -> a) -> a -> a -> Bool
forall a b. Eq a => (b -> b -> a) -> (b -> b) -> a -> b -> Bool
Laws.inverse a -> a -> a
forall a. C a => a -> a -> a
(+) a -> a
forall a. C a => a -> a
negate a
forall a. C a => a
zero



-- legacy

instance (P.Integral a) => C (Ratio98.Ratio a) where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Ratio a
zero                =  Integer -> Ratio a
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   + :: Ratio a -> Ratio a -> Ratio a
(+)                 =  Ratio a -> Ratio a -> Ratio a
forall a. Num a => a -> a -> a
(P.+)
   (-)                 =  Ratio a -> Ratio a -> Ratio a
forall a. Num a => a -> a -> a
(P.-)
   negate :: Ratio a -> Ratio a
negate              =  Ratio a -> Ratio a
forall a. Num a => a -> a
P.negate

instance (P.RealFloat a) => C (Complex98.Complex a) where
   {-# INLINE zero #-}
   {-# INLINE negate #-}
   {-# INLINE (+) #-}
   {-# INLINE (-) #-}
   zero :: Complex a
zero                =  Integer -> Complex a
forall a. Num a => Integer -> a
P.fromInteger Integer
0
   + :: Complex a -> Complex a -> Complex a
(+)                 =  Complex a -> Complex a -> Complex a
forall a. Num a => a -> a -> a
(P.+)
   (-)                 =  Complex a -> Complex a -> Complex a
forall a. Num a => a -> a -> a
(P.-)
   negate :: Complex a -> Complex a
negate              =  Complex a -> Complex a
forall a. Num a => a -> a
P.negate