module Plankton.Additive
  ( AdditiveMagma(..)
  , AdditiveUnital(..)
  , AdditiveAssociative
  , AdditiveCommutative
  , AdditiveInvertible(..)
  , AdditiveIdempotent
  , sum
  , Additive(..)
  , AdditiveRightCancellative(..)
  , AdditiveLeftCancellative(..)
  , AdditiveGroup(..)
  ) where
import Data.Complex (Complex(..))
import qualified Protolude as P
import Protolude (Bool(..), Double, Float, Int, Integer)
class AdditiveMagma a where
  plus :: a -> a -> a
instance AdditiveMagma Double where
  plus = (P.+)
instance AdditiveMagma Float where
  plus = (P.+)
instance AdditiveMagma Int where
  plus = (P.+)
instance AdditiveMagma Integer where
  plus = (P.+)
instance AdditiveMagma Bool where
  plus = (P.||)
instance (AdditiveMagma a) => AdditiveMagma (Complex a) where
  (rx :+ ix) `plus` (ry :+ iy) = (rx `plus` ry) :+ (ix `plus` iy)
class AdditiveMagma a =>
      AdditiveUnital a where
  zero :: a
instance AdditiveUnital Double where
  zero = 0
instance AdditiveUnital Float where
  zero = 0
instance AdditiveUnital Int where
  zero = 0
instance AdditiveUnital Integer where
  zero = 0
instance AdditiveUnital Bool where
  zero = False
instance (AdditiveUnital a) => AdditiveUnital (Complex a) where
  zero = zero :+ zero
class AdditiveMagma a =>
      AdditiveAssociative a
instance AdditiveAssociative Double
instance AdditiveAssociative Float
instance AdditiveAssociative Int
instance AdditiveAssociative Integer
instance AdditiveAssociative Bool
instance (AdditiveAssociative a) => AdditiveAssociative (Complex a)
class AdditiveMagma a =>
      AdditiveCommutative a
instance AdditiveCommutative Double
instance AdditiveCommutative Float
instance AdditiveCommutative Int
instance AdditiveCommutative Integer
instance AdditiveCommutative Bool
instance (AdditiveCommutative a) => AdditiveCommutative (Complex a)
class AdditiveMagma a =>
      AdditiveInvertible a where
  negate :: a -> a
instance AdditiveInvertible Double where
  negate = P.negate
instance AdditiveInvertible Float where
  negate = P.negate
instance AdditiveInvertible Int where
  negate = P.negate
instance AdditiveInvertible Integer where
  negate = P.negate
instance AdditiveInvertible Bool where
  negate = P.not
instance (AdditiveInvertible a) => AdditiveInvertible (Complex a) where
  negate (rx :+ ix) = negate rx :+ negate ix
class AdditiveMagma a =>
      AdditiveIdempotent a
instance AdditiveIdempotent Bool
sum :: (Additive a, P.Foldable f) => f a -> a
sum = P.foldr (+) zero
class (AdditiveCommutative a, AdditiveUnital a, AdditiveAssociative a) =>
      Additive a where
  infixl 6 +
  (+) :: a -> a -> a
  a + b = plus a b
instance Additive Double
instance Additive Float
instance Additive Int
instance Additive Integer
instance Additive Bool
instance (Additive a) => Additive (Complex a)
class (AdditiveUnital a, AdditiveAssociative a, AdditiveInvertible a) =>
      AdditiveLeftCancellative a where
  infixl 6 ~-
  (~-) :: a -> a -> a
  (~-) a b = negate b `plus` a
class (AdditiveUnital a, AdditiveAssociative a, AdditiveInvertible a) =>
      AdditiveRightCancellative a where
  infixl 6 -~
  (-~) :: a -> a -> a
  (-~) a b = a `plus` negate b
class (Additive a, AdditiveInvertible a) =>
      AdditiveGroup a where
  infixl 6 
  () :: a -> a -> a
  () a b = a `plus` negate b
instance AdditiveGroup Double
instance AdditiveGroup Float
instance AdditiveGroup Int
instance AdditiveGroup Integer
instance (AdditiveGroup a) => AdditiveGroup (Complex a)