module Algebra.Units (
C,
isUnit,
stdAssociate,
stdUnit,
stdUnitInv,
intQuery,
intAssociate,
intStandard,
intStandardInverse,
propComposition,
propInverseUnit,
propUniqueAssociate,
propAssociateProduct,
) where
import qualified Algebra.IntegralDomain as Integral
import qualified Algebra.Ring as Ring
import qualified Algebra.ZeroTestable as ZeroTestable
import qualified Algebra.Laws as Laws
import Algebra.IntegralDomain (div)
import Algebra.Ring (one, (*))
import Algebra.Additive (negate)
import Algebra.ZeroTestable (isZero)
import Data.Int (Int, Int8, Int16, Int32, Int64, )
import NumericPrelude.Base
import Prelude (Integer, )
import qualified Prelude as P
import Test.QuickCheck ((==>), Property)
class (Integral.C a) => C a where
isUnit :: a -> Bool
stdAssociate, stdUnit, stdUnitInv :: a -> a
stdAssociate x = x * stdUnitInv x
stdUnit x = div one (stdUnitInv x)
stdUnitInv x = div one (stdUnit x)
intQuery :: (P.Integral a, Ring.C a) => a -> Bool
intQuery = flip elem [one, negate one]
intAssociate, intStandard, intStandardInverse ::
(P.Integral a, Ring.C a, ZeroTestable.C a) => a -> a
intAssociate = P.abs
intStandard x = if isZero x then one else P.signum x
intStandardInverse = intStandard
instance C Int where
isUnit = intQuery
stdAssociate = intAssociate
stdUnit = intStandard
stdUnitInv = intStandardInverse
instance C Integer where
isUnit = intQuery
stdAssociate = intAssociate
stdUnit = intStandard
stdUnitInv = intStandardInverse
instance C Int8 where
isUnit = intQuery
stdAssociate = intAssociate
stdUnit = intStandard
stdUnitInv = intStandardInverse
instance C Int16 where
isUnit = intQuery
stdAssociate = intAssociate
stdUnit = intStandard
stdUnitInv = intStandardInverse
instance C Int32 where
isUnit = intQuery
stdAssociate = intAssociate
stdUnit = intStandard
stdUnitInv = intStandardInverse
instance C Int64 where
isUnit = intQuery
stdAssociate = intAssociate
stdUnit = intStandard
stdUnitInv = intStandardInverse
propComposition :: (Eq a, C a) => a -> Bool
propInverseUnit :: (Eq a, C a) => a -> Bool
propUniqueAssociate :: (Eq a, C a) => a -> a -> Property
propAssociateProduct :: (Eq a, C a) => a -> a -> Bool
propComposition x = stdAssociate x * stdUnit x == x
propInverseUnit x = stdUnit x * stdUnitInv x == one
propUniqueAssociate u x =
isUnit u ==> stdAssociate x == stdAssociate (x*u)
propAssociateProduct =
Laws.homomorphism stdAssociate (*) (*)