module Data.Semigroup (
Semigroup(..)
, Min(..)
, Max(..)
, Option(..)
, WrappedMonoid(..)
) where
import Prelude hiding (foldr1)
import Data.Monoid
import Data.Foldable
infixl 4 <>
class Semigroup a where
(<>) :: a -> a -> a
fold1 :: Foldable f => f a -> a
fold1 = foldr1 (<>)
instance Semigroup a => Semigroup (Dual a) where
Dual a <> Dual b = Dual (b <> a)
instance Semigroup (Endo a) where
Endo f <> Endo g = Endo (f . g)
instance Semigroup All where
All a <> All b = All (a && b)
instance Semigroup Any where
Any a <> Any b = Any (a || b)
instance Num a => Semigroup (Sum a) where
Sum a <> Sum b = Sum (a + b)
instance Num a => Semigroup (Product a) where
Product a <> Product b = Product (a * b)
instance Semigroup (First a) where
First Nothing <> b = b
a <> _ = a
instance Semigroup (Last a) where
a <> Last Nothing = a
_ <> b = b
newtype Min a = Min { getMin :: a }
instance Ord a => Semigroup (Min a) where
Min a <> Min b = Min (a `min` b)
newtype Max a = Max { getMax :: a }
instance Ord a => Semigroup (Max a) where
Max a <> Max b = Max (a `min` b)
newtype WrappedMonoid m = WrapMonoid { unwrapMonoid :: m }
deriving (Show, Read, Eq, Ord)
instance Monoid m => Semigroup (WrappedMonoid m) where
WrapMonoid a <> WrapMonoid b = WrapMonoid (a `mappend` b)
instance Monoid m => Monoid (WrappedMonoid m) where
mempty = WrapMonoid mempty
WrapMonoid a `mappend` WrapMonoid b = WrapMonoid (a `mappend` b)
newtype Option a = Option { runOption :: Maybe a }
deriving (Show, Read, Eq, Ord)
instance Semigroup a => Semigroup (Option a) where
Option Nothing <> b = b
a <> Option Nothing = a
Option (Just a) <> Option (Just b) = Option (Just (a <> b))
instance Semigroup a => Monoid (Option a) where
mempty = Option Nothing
Option Nothing `mappend` b = b
a `mappend` Option Nothing = a
Option (Just a) `mappend` Option (Just b) = Option (Just (a <> b))