-------------------------------------------------------------------------------- -- | -- Module : Data.Monus -- Copyright : (c) Donnacha Oisín Kidney 2021 -- Maintainer : mail@doisinkidney.com -- Stability : experimental -- Portability : non-portable -- -- A class for 'Monoid's with an order and a pseudo-subtraction operator. -------------------------------------------------------------------------------- module Data.Monus (Monus(..)) where import Data.Monoid (Sum(..), Any(..)) import Data.Semigroup (Max(..)) -- $setup -- >>> import Data.Monoid (Any(..)) infixl 6 |-| -- | A class for (constructive) totally-ordered commutative monoids. These -- are monoids such that their ordering respects the '<>' operator, meaning -- they obey the following law: -- -- @ -- x '<=' x '<>' y -- @ -- -- These monoids must also have a pseudo-subtraction operator ('|-|'), which -- behaves like an absolute difference function. This operator must obey the -- following law: -- -- @ -- x '<=' y ==> x '<>' (y '|-|' x) '==' y -- @ class (Ord a, Monoid a) => Monus a where -- | An absolute difference operator. (|-|) :: a -> a -> a instance (Num a, Ord a) => Monus (Sum a) where Sum a x |-| :: Sum a -> Sum a -> Sum a |-| Sum a y | a x a -> a -> Bool forall a. Ord a => a -> a -> Bool <= a y = a -> Sum a forall a. a -> Sum a Sum (a y a -> a -> a forall a. Num a => a -> a -> a - a x) | Bool otherwise = a -> Sum a forall a. a -> Sum a Sum (a x a -> a -> a forall a. Num a => a -> a -> a - a y) {-# INLINE (|-|) #-} -- | -- -- >>> let bools = [Any False, Any True] -- >>> and [ x <> (y |-| x) == y | x <- bools, y <- bools, x <= y ] -- True instance Monus Any where |-| :: Any -> Any -> Any (|-|) = Any -> Any -> Any forall a. Semigroup a => a -> a -> a (<>) {-# INLINE (|-|) #-} instance (Bounded a, Ord a) => Monus (Max a) where |-| :: Max a -> Max a -> Max a (|-|) = Max a -> Max a -> Max a forall a. Semigroup a => a -> a -> a (<>) {-# INLINE (|-|) #-}