{-# language TypeFamilies #-} {-# language ScopedTypeVariables #-} {-# language RankNTypes #-} -- | A -- is a 'Monoid' equipped with a subtraction operator. module Data.Monoid.Monus ( Monus(..) , (-) ) where import Prelude hiding ((-)) import Data.Set (Set) import Data.Complex (Complex(..)) import Data.Monoid (Any(..),All(..),Sum(..), Endo(..)) import Control.Applicative (liftA2) import Numeric.Natural (Natural) import Data.Foldable import Data.Coerce import qualified Prelude as P import qualified Data.Set as S infixl 6 - -- | A commutative monoid that supports subtraction. The following -- laws must hold: -- -- > x <> (y - x) = y <> (x - y) -- > (x - y) - z = x - (y <> z) -- > x - x = mempty -- > mempty - x = mempty class Monoid a => Monus a where monus :: a -> a -> a -- | An infix synonym for 'subtraction'. (-) :: Monus a => a -> a -> a (-) = monus {-# INLINE (-) #-} instance Ord a => Monus (Set a) where monus = S.difference {-# INLINE monus #-} -- | Unlike the subtraction provided by the 'Num' instance of -- 'Natural', this subtraction is total. instance (a ~ Natural) => Monus (Sum a) where monus (Sum x) (Sum y) = Sum (if x > y then x P.- y else 0) {-# INLINE monus #-} -- | Defined as @P - Q = P ∧ ¬Q@ instance Monus Any where monus (Any x) (Any y) = case x of False -> Any False True -> Any (not y) {-# INLINE monus #-} -- | Defined as @P - Q = P ∨ ¬Q@ instance Monus All where monus (All x) (All y) = case x of False -> All (not y) True -> All True {-# INLINE monus #-} instance forall a. Monus a => Monus (Endo a) where monus = coerce (liftA2 monus :: (a -> a) -> (a -> a) -> (a -> a)) {-# INLINE monus #-} instance Monus () where monus _ _ = () {-# INLINE monus #-} instance (Monus a, Monus b) => Monus (a,b) where monus (a1,b1) (a2,b2) = (monus a1 a2,monus b1 b2) {-# INLINE monus #-} instance (Monus a, Monus b, Monus c) => Monus (a,b,c) where monus (a1,b1,c1) (a2,b2,c2) = (monus a1 a2,monus b1 b2,monus c1 c2) {-# INLINE monus #-} instance (Monus a, Monus b, Monus c,Monus d) => Monus (a,b,c,d) where monus (a1,b1,c1,d1) (a2,b2,c2,d2) = (monus a1 a2,monus b1 b2,monus c1 c2,monus d1 d2) {-# INLINE monus #-} instance (Monus a, Monus b, Monus c,Monus d,Monus e) => Monus (a,b,c,d,e) where monus (a1,b1,c1,d1,e1) (a2,b2,c2,d2,e2) = (monus a1 a2,monus b1 b2,monus c1 c2,monus d1 d2,monus e1 e2) {-# INLINE monus #-} instance Monus b => Monus (a -> b) where monus = liftA2 monus {-# INLINE monus #-} instance Monus a => Monus (IO a) where monus = liftA2 monus {-# INLINE monus #-} instance Monus a => Monus [a] where monus [] _ = [] monus x [] = x monus (x:xs) (y:ys) = monus x y : monus xs ys instance Monus a => Monus (Maybe a) where monus = liftA2 monus {-# INLINE monus #-}