{-# LANGUAGE CPP #-}
{-# LANGUAGE ViewPatterns #-}

-- | Provides the 'MMonoid' typeclass.
--
-- @since 0.1
module Numeric.Algebra.Multiplicative.MMonoid
  ( MMonoid (..),
    pattern One,
    pattern NonOne,
  )
where

import Data.Complex (Complex)
import Data.Fixed (Fixed, HasResolution)
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Kind (Constraint, Type)
import Data.Ratio (Ratio)
import Data.Word (Word16, Word32, Word64, Word8)
import GHC.Natural (Natural)
import Numeric.Algebra.Multiplicative.MSemigroup (MSemigroup)

-- | Defines a monoid over a multiplicative semigroup.
--
-- @since 0.1
type MMonoid :: Type -> Constraint
class (MSemigroup m) => MMonoid m where
  -- | @since 0.1
  one :: m

-- | Pattern synonym for 'one'.
--
-- @since 0.1
pattern One :: (MMonoid m, Eq m) => m
pattern $mOne :: forall {r} {m}.
(MMonoid m, Eq m) =>
m -> ((# #) -> r) -> ((# #) -> r) -> r
$bOne :: forall m. (MMonoid m, Eq m) => m
One <- ((== one) -> True)
  where
    One = m
forall m. MMonoid m => m
one

-- | Pattern synonym for @x /= 'one'@.
--
-- @since 0.1
pattern NonOne :: (MMonoid m, Eq m) => m -> m
pattern $mNonOne :: forall {r} {m}.
(MMonoid m, Eq m) =>
m -> (m -> r) -> ((# #) -> r) -> r
NonOne y <- (\m
x -> (m
x m -> m -> Bool
forall a. Eq a => a -> a -> Bool
== m
forall m. MMonoid m => m
one, m
x) -> (False, y))

-- see NOTE: [Pattern Synonym COMPLETE]

#if MIN_VERSION_base(4, 16, 0)
{-# COMPLETE One, NonOne #-}
#endif

-- | @since 0.1
instance MMonoid Double where
  one :: Double
one = Double
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Float where
  one :: Float
one = Float
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Int where
  one :: Int
one = Int
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Int8 where
  one :: Int8
one = Int8
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Int16 where
  one :: Int16
one = Int16
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Int32 where
  one :: Int32
one = Int32
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Int64 where
  one :: Int64
one = Int64
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Integer where
  one :: Integer
one = Integer
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Word where
  one :: Word
one = Word
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Word8 where
  one :: Word8
one = Word8
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Word16 where
  one :: Word16
one = Word16
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Word32 where
  one :: Word32
one = Word32
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Word64 where
  one :: Word64
one = Word64
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid Natural where
  one :: Natural
one = Natural
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid (Ratio Integer) where
  one :: Ratio Integer
one = Ratio Integer
1
  {-# INLINE one #-}

-- | @since 0.1
instance MMonoid (Ratio Natural) where
  one :: Ratio Natural
one = Ratio Natural
1
  {-# INLINE one #-}

-- | @since 0.1
instance (RealFloat a) => MMonoid (Complex a) where
  one :: Complex a
one = Complex a
1
  {-# INLINE one #-}

-- | @since 0.1
instance (HasResolution k) => MMonoid (Fixed k) where
  one :: Fixed k
one = Fixed k
1
  {-# INLINE one #-}