module Numeric.Partial.Group ( PartialGroup(..) ) where import Control.Applicative import Data.Int import Data.Word import Numeric.Partial.Semigroup import Numeric.Partial.Monoid import Numeric.Natural class PartialMonoid a => PartialGroup a where pnegate :: a -> Maybe a pnegate = pminus pzero pminus :: a -> a -> Maybe a pminus a b = padd a =<< pnegate b psubtract :: a -> a -> Maybe a psubtract a b = pnegate a >>= (`padd` b) instance PartialGroup Int where pnegate = Just . negate instance PartialGroup Integer where pnegate = Just . negate instance PartialGroup Int8 where pnegate = Just . negate instance PartialGroup Int16 where pnegate = Just . negate instance PartialGroup Int32 where pnegate = Just . negate instance PartialGroup Int64 where pnegate = Just . negate instance PartialGroup Word where pnegate = Just . negate instance PartialGroup Word8 where pnegate = Just . negate instance PartialGroup Word16 where pnegate = Just . negate instance PartialGroup Word32 where pnegate = Just . negate instance PartialGroup Word64 where pnegate = Just . negate instance PartialGroup Natural where pnegate 0 = Just 0 pnegate _ = Nothing pminus a b | a < b = Nothing | otherwise = Just (a - b) psubtract a b | a > b = Nothing | otherwise = Just (b - a) instance PartialGroup () where pnegate _ = Just () pminus _ _ = Just () psubtract _ _ = Just () instance (PartialGroup a, PartialGroup b) => PartialGroup (a, b) where pnegate (a, b) = (,) <$> pnegate a <*> pnegate b pminus (a, b) (i, j) = (,) <$> pminus a i <*> pminus b j psubtract (a, b) (i, j) = (,) <$> psubtract a i <*> psubtract b j instance (PartialGroup a, PartialGroup b, PartialGroup c) => PartialGroup (a, b, c) where pnegate (a, b, c) = (,,) <$> pnegate a <*> pnegate b <*> pnegate c pminus (a, b, c) (i, j, k) = (,,) <$> pminus a i <*> pminus b j <*> pminus c k psubtract (a, b, c) (i, j, k) = (,,) <$> psubtract a i <*> psubtract b j <*> psubtract c k instance (PartialGroup a, PartialGroup b, PartialGroup c, PartialGroup d) => PartialGroup (a, b, c, d) where pnegate (a, b, c, d) = (,,,) <$> pnegate a <*> pnegate b <*> pnegate c <*> pnegate d pminus (a, b, c, d) (i, j, k, l) = (,,,) <$> pminus a i <*> pminus b j <*> pminus c k <*> pminus d l psubtract (a, b, c, d) (i, j, k, l) = (,,,) <$> psubtract a i <*> psubtract b j <*> psubtract c k <*> psubtract d l instance (PartialGroup a, PartialGroup b, PartialGroup c, PartialGroup d, PartialGroup e) => PartialGroup (a, b, c, d, e) where pnegate (a, b, c, d, e) = (,,,,) <$> pnegate a <*> pnegate b <*> pnegate c <*> pnegate d <*> pnegate e pminus (a, b, c, d, e) (i, j, k, l, m) = (,,,,) <$> pminus a i <*> pminus b j <*> pminus c k <*> pminus d l <*> pminus e m psubtract (a, b, c, d, e) (i, j, k, l, m) = (,,,,) <$> psubtract a i <*> psubtract b j <*> psubtract c k <*> psubtract d l <*> psubtract e m