numhask-0.2.2.0: src/NumHask/Algebra/Multiplicative.hs
{-# OPTIONS_GHC -Wall #-}
-- | A magma heirarchy for multiplication. The basic magma structure is repeated and prefixed with 'Multiplicative-'.
module NumHask.Algebra.Multiplicative
( MultiplicativeMagma(..)
, MultiplicativeUnital(..)
, MultiplicativeAssociative
, MultiplicativeCommutative
, MultiplicativeInvertible(..)
, product
, Multiplicative(..)
, MultiplicativeRightCancellative(..)
, MultiplicativeLeftCancellative(..)
, MultiplicativeGroup(..)
, MultiplicativeIdempotent
) where
import Data.Complex (Complex(..))
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Word (Word, Word8, Word16, Word32, Word64)
import GHC.Natural (Natural(..))
import NumHask.Algebra.Additive
import qualified Prelude as P
import Prelude (Bool(..), Double, Float, Int, Integer)
-- | 'times' is used as the operator for the multiplicative magam to distinguish from '*' which, by convention, implies commutativity
--
-- > ∀ a,b ∈ A: a `times` b ∈ A
--
-- law is true by construction in Haskell
class MultiplicativeMagma a where
times :: a -> a -> a
instance MultiplicativeMagma Double where
times = (P.*)
instance MultiplicativeMagma Float where
times = (P.*)
instance MultiplicativeMagma Int where
times = (P.*)
instance MultiplicativeMagma Integer where
times = (P.*)
instance MultiplicativeMagma Bool where
times = (P.&&)
instance (MultiplicativeMagma a, AdditiveGroup a) =>
MultiplicativeMagma (Complex a) where
(rx :+ ix) `times` (ry :+ iy) =
(rx `times` ry - ix `times` iy) :+ (ix `times` ry + iy `times` rx)
instance MultiplicativeMagma Natural where
times = (P.*)
instance MultiplicativeMagma Int8 where
times = (P.*)
instance MultiplicativeMagma Int16 where
times = (P.*)
instance MultiplicativeMagma Int32 where
times = (P.*)
instance MultiplicativeMagma Int64 where
times = (P.*)
instance MultiplicativeMagma Word where
times = (P.*)
instance MultiplicativeMagma Word8 where
times = (P.*)
instance MultiplicativeMagma Word16 where
times = (P.*)
instance MultiplicativeMagma Word32 where
times = (P.*)
instance MultiplicativeMagma Word64 where
times = (P.*)
-- | Unital magma for multiplication.
--
-- > one `times` a == a
-- > a `times` one == a
class MultiplicativeMagma a =>
MultiplicativeUnital a where
one :: a
instance MultiplicativeUnital Double where
one = 1
instance MultiplicativeUnital Float where
one = 1
instance MultiplicativeUnital Int where
one = 1
instance MultiplicativeUnital Integer where
one = 1
instance MultiplicativeUnital Bool where
one = True
instance (AdditiveUnital a, AdditiveGroup a, MultiplicativeUnital a) =>
MultiplicativeUnital (Complex a) where
one = one :+ zero
instance MultiplicativeUnital Natural where
one = 1
instance MultiplicativeUnital Int8 where
one = 1
instance MultiplicativeUnital Int16 where
one = 1
instance MultiplicativeUnital Int32 where
one = 1
instance MultiplicativeUnital Int64 where
one = 1
instance MultiplicativeUnital Word where
one = 1
instance MultiplicativeUnital Word8 where
one = 1
instance MultiplicativeUnital Word16 where
one = 1
instance MultiplicativeUnital Word32 where
one = 1
instance MultiplicativeUnital Word64 where
one = 1
-- | Associative magma for multiplication.
--
-- > (a `times` b) `times` c == a `times` (b `times` c)
class MultiplicativeMagma a =>
MultiplicativeAssociative a
instance MultiplicativeAssociative Double
instance MultiplicativeAssociative Float
instance MultiplicativeAssociative Int
instance MultiplicativeAssociative Integer
instance MultiplicativeAssociative Bool
instance (AdditiveGroup a, MultiplicativeAssociative a) =>
MultiplicativeAssociative (Complex a)
instance MultiplicativeAssociative Natural
instance MultiplicativeAssociative Int8
instance MultiplicativeAssociative Int16
instance MultiplicativeAssociative Int32
instance MultiplicativeAssociative Int64
instance MultiplicativeAssociative Word
instance MultiplicativeAssociative Word8
instance MultiplicativeAssociative Word16
instance MultiplicativeAssociative Word32
instance MultiplicativeAssociative Word64
-- | Commutative magma for multiplication.
--
-- > a `times` b == b `times` a
class MultiplicativeMagma a =>
MultiplicativeCommutative a
instance MultiplicativeCommutative Double
instance MultiplicativeCommutative Float
instance MultiplicativeCommutative Int
instance MultiplicativeCommutative Integer
instance MultiplicativeCommutative Bool
instance (AdditiveGroup a, MultiplicativeCommutative a) =>
MultiplicativeCommutative (Complex a)
instance MultiplicativeCommutative Natural
instance MultiplicativeCommutative Int8
instance MultiplicativeCommutative Int16
instance MultiplicativeCommutative Int32
instance MultiplicativeCommutative Int64
instance MultiplicativeCommutative Word
instance MultiplicativeCommutative Word8
instance MultiplicativeCommutative Word16
instance MultiplicativeCommutative Word32
instance MultiplicativeCommutative Word64
-- | Invertible magma for multiplication.
--
-- > ∀ a ∈ A: recip a ∈ A
--
-- law is true by construction in Haskell
class MultiplicativeMagma a =>
MultiplicativeInvertible a where
recip :: a -> a
instance MultiplicativeInvertible Double where
recip = P.recip
instance MultiplicativeInvertible Float where
recip = P.recip
instance (AdditiveGroup a, MultiplicativeInvertible a) =>
MultiplicativeInvertible (Complex a) where
recip (rx :+ ix) = (rx `times` d) :+ (negate ix `times` d)
where
d = recip ((rx `times` rx) `plus` (ix `times` ix))
-- | Idempotent magma for multiplication.
--
-- > a `times` a == a
class MultiplicativeMagma a =>
MultiplicativeIdempotent a
instance MultiplicativeIdempotent Bool
-- | product definition avoiding a clash with the Product monoid in base
-- fixme: fit in with Product in base
--
product :: (Multiplicative a, P.Foldable f) => f a -> a
product = P.foldr (*) one
-- | Multiplicative is commutative, associative and unital under multiplication
--
-- > one * a == a
-- > a * one == a
-- > (a * b) * c == a * (b * c)
-- > a * b == b * a
class ( MultiplicativeCommutative a
, MultiplicativeUnital a
, MultiplicativeAssociative a
) =>
Multiplicative a where
infixl 7 *
(*) :: a -> a -> a
a * b = times a b
instance Multiplicative Double
instance Multiplicative Float
instance Multiplicative Int
instance Multiplicative Integer
instance Multiplicative Bool
instance (AdditiveGroup a, Multiplicative a) => Multiplicative (Complex a)
instance Multiplicative Natural
instance Multiplicative Int8
instance Multiplicative Int16
instance Multiplicative Int32
instance Multiplicative Int64
instance Multiplicative Word
instance Multiplicative Word8
instance Multiplicative Word16
instance Multiplicative Word32
instance Multiplicative Word64
-- | Non-commutative left divide
--
-- > recip a `times` a = one
class ( MultiplicativeUnital a
, MultiplicativeAssociative a
, MultiplicativeInvertible a
) =>
MultiplicativeLeftCancellative a where
infixl 7 ~/
(~/) :: a -> a -> a
a ~/ b = recip b `times` a
-- | Non-commutative right divide
--
-- > a `times` recip a = one
class ( MultiplicativeUnital a
, MultiplicativeAssociative a
, MultiplicativeInvertible a
) =>
MultiplicativeRightCancellative a where
infixl 7 /~
(/~) :: a -> a -> a
a /~ b = a `times` recip b
-- | Divide ('/') is reserved for where both the left and right cancellative laws hold. This then implies that the MultiplicativeGroup is also Abelian.
--
-- > a / a = one
-- > recip a = one / a
-- > recip a * a = one
-- > a * recip a = one
class (Multiplicative a, MultiplicativeInvertible a) =>
MultiplicativeGroup a where
infixl 7 /
(/) :: a -> a -> a
(/) a b = a `times` recip b
instance MultiplicativeGroup Double
instance MultiplicativeGroup Float
instance (AdditiveGroup a, MultiplicativeGroup a) =>
MultiplicativeGroup (Complex a)