module Data.Semigroup(
Semigroup((.++.)),
Identity,
(<++>)
) where
import Data.Monoid
import Control.Applicative
class Semigroup a where
(.++.) :: a -> a -> a
newtype Identity a = Identity { run :: a }
(<++>) :: (Applicative f, Semigroup a) => f a -> f a -> f a
(<++>) = liftA2 (.++.)
instance Functor Identity where
fmap f (Identity a) = Identity (f a)
instance Applicative Identity where
pure = Identity
Identity f <*> Identity a = Identity (f a)
instance Monad Identity where
return = Identity
Identity a >>= f = f a
instance Monoid a => Semigroup (Identity a) where
(.++.) = liftA2 mappend
instance Semigroup () where
_ .++. _ = ()
instance Semigroup b => Semigroup (a -> b) where
(.++.) = (<++>)
instance Semigroup a => Semigroup (IO a) where
(.++.) = (<++>)
instance (Semigroup a, Semigroup b) => Semigroup (a, b) where
(a1, b1) .++. (a2, b2) = (a1 .++. a2, b1 .++. b2)
instance (Semigroup a, Semigroup b, Semigroup c) => Semigroup (a, b, c) where
(a1, b1, c1) .++. (a2, b2, c2) = (a1 .++. a2, b1 .++. b2, c1 .++. c2)
instance Semigroup All where
a .++. b = run (Identity a .++. Identity b)
instance Semigroup Any where
a .++. b = run (Identity a .++. Identity b)
instance Semigroup a => Semigroup (Dual a) where
Dual a .++. Dual b = Dual (b .++. a)
instance Semigroup (Endo a) where
a .++. b = run (Identity a .++. Identity b)
instance Num a => Semigroup (Product a) where
a .++. b = run (Identity a .++. Identity b)
instance Num a => Semigroup (Sum a) where
a .++. b = run (Identity a .++. Identity b)
instance Semigroup a => Semigroup (Maybe a) where
Nothing .++. b = b
a .++. Nothing = a
Just a .++. Just b = Just (a .++. b)
instance Semigroup (First a) where
a .++. b = run (Identity a .++. Identity b)
instance Semigroup (Last a) where
a .++. b = run (Identity a .++. Identity b)
instance Semigroup [a] where
(.++.) = (++)