{-# LANGUAGE CPP #-}
module Data.Semigroup.SSet
( SSet (..)
, rep
, fact
, S (..)
) where
import Data.Semigroup (Semigroup (..), Endo (..), Sum (..), Product (..))
import Data.Functor.Const (Const (..))
import Data.Functor.Identity (Identity (..))
import qualified Data.Functor.Product as Functor (Product)
import qualified Data.Functor.Sum as Functor (Sum)
import Data.Group (Group (..))
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NE
import Data.Natural (Natural)
import Data.Ord (Down (..))
import Data.Set (Set)
import qualified Data.Set as Set
class Semigroup s => SSet s a where
act :: s -> a -> a
rep :: SSet s a => s -> Endo a
rep s = Endo (act s)
instance {-# OVERLAPPABLE #-} Semigroup s => SSet (s) (s) where
act = (<>)
instance (SSet s a, SSet s b) => SSet s (a, b) where
act s (a, b) = (act s a, act s b)
instance (SSet s a, SSet s b, SSet s c) => SSet s (a, b, c) where
act s (a, b, c) = (act s a, act s b, act s c)
instance (SSet s a, SSet s b, SSet s c, SSet s d) => SSet s (a, b, c, d) where
act s (a, b, c, d) = (act s a, act s b, act s c, act s d)
instance (SSet s a, SSet s b, SSet s c, SSet s d, SSet s e) => SSet s (a, b, c, d, e) where
act s (a, b, c, d, e) = (act s a, act s b, act s c, act s d, act s e)
instance (SSet s a, SSet s b, SSet s c, SSet s d, SSet s e, SSet s f) => SSet s (a, b, c, d, e, f) where
act s (a, b, c, d, e, f) = (act s a, act s b, act s c, act s d, act s e, act s f)
instance (SSet s a, SSet s b, SSet s c, SSet s d, SSet s e, SSet s f, SSet s h) => SSet s (a, b, c, d, e, f, h) where
act s (a, b, c, d, e, f, h) = (act s a, act s b, act s c, act s d, act s e, act s f, act s h)
instance (SSet s a, SSet s b, SSet s c, SSet s d, SSet s e, SSet s f, SSet s h, SSet s i) => SSet s (a, b, c, d, e, f, h, i) where
act s (a, b, c, d, e, f, h, i) = (act s a, act s b, act s c, act s d, act s e, act s f, act s h, act s i)
instance SSet s a => SSet s [a] where
act s = map (act s)
instance SSet s a => SSet s (NonEmpty a) where
act s as = NE.map (act s) as
instance (SSet s a, Ord a) => SSet s (Set a) where
act s as = Set.map (act s) as
fact :: (Functor f, SSet s a) => s -> f a -> f a
fact s = fmap (act s)
instance SSet s a => SSet s (Identity a) where
act = fact
instance SSet s a => SSet (Identity s) a where
act (Identity f) a = f `act` a
instance SSet s a => SSet s (Maybe a) where
act = fact
instance SSet s b => SSet s (Either a b) where
act = fact
instance SSet s a => SSet s (Down a) where
act s (Down a) = Down (act s a)
instance SSet s a => SSet s (IO a) where
act = fact
instance SSet s b => SSet s (a -> b) where
act = fact
instance SSet (Endo a) a where
act = appEndo
newtype S s = S { runS :: s }
deriving (Eq, Show, Ord)
instance Semigroup m => Semigroup (S m) where
S s <> S s' = S $ s <> s'
instance Monoid m => Monoid (S m) where
mempty = S mempty
#if __GLASGOW_HASKELL__ < 804
S s `mappend` S s' = S $ s `mappend` s'
#endif
instance SSet s a => SSet (S s) (Endo a) where
act (S s) (Endo f) = Endo $ act s . f
instance Monoid s => SSet (Sum Natural) s where
act (Sum 0) _ = mempty
act (Sum n) s = s `mappend` act (Sum (n - 1)) s
instance Group g => SSet (Sum Integer) g where
act (Sum n) g | n < 0 = invert g `mappend` act (Sum (n + 1)) g
| n > 0 = g `mappend` act (Sum (n - 1)) g
| otherwise = mempty
instance SSet s a => SSet s (Const a b) where
act s (Const a) = Const $ s `act` a
instance (Functor f, Functor h, SSet s a) => SSet s (Functor.Product f h a) where
act = fact
instance (Functor f, Functor h, SSet s a) => SSet s (Functor.Sum f h a) where
act = fact
instance Num s => SSet (Sum s) s where
act (Sum n) s = n + s
instance Num s => SSet (Product s) s where
act (Product n) s = n * s