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.Additive as Additive
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, Int)
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 (*) (*)