-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Group.Multiplicative
-- Copyright   :  (c) Edward Kmett 2009
-- License     :  BSD-style
-- Maintainer  :  ekmett@gmail.com
-- Stability   :  experimental
-- Portability :  portable
--
-----------------------------------------------------------------------------

module Data.Group.Multiplicative 
    ( module Data.Monoid.Multiplicative
    , module Data.Group
    , MultiplicativeGroup
    , over
    , under
    , grecip
    ) where

import Data.Monoid.Multiplicative
import Data.Group
import Data.Monoid.Self
import Data.Monoid.FromString
import Data.Monoid.Reducer

    
-- | Minimal definition over or grecip
class Multiplicative g => MultiplicativeGroup g where
    -- | @x / y@
    over :: g -> g -> g
    -- | @x \ y@
    under :: g -> g -> g
    grecip :: g -> g

    x `under` y = grecip x `times` y
    x `over` y = x `times` grecip y
    grecip x = one `over` x

instance MultiplicativeGroup g => MultiplicativeGroup (Self g) where
    Self x `over` Self y = Self (x `over` y)
    Self x `under` Self y = Self (x `under` y)
    grecip (Self x) = Self (grecip x)

instance MultiplicativeGroup g => MultiplicativeGroup (FromString g) where
    FromString x `over` FromString y = FromString (x `over` y)
    FromString x `under` FromString y = FromString (x `under` y)
    grecip (FromString x) = FromString (grecip x)

instance MultiplicativeGroup g => MultiplicativeGroup (ReducedBy g s) where
    Reduction x `over` Reduction y = Reduction (x `over` y)
    Reduction x `under` Reduction y = Reduction (x `under` y)
    grecip (Reduction x) = Reduction (grecip x)

instance MultiplicativeGroup a => MultiplicativeGroup (Dual a) where
    grecip = Dual . grecip . getDual