module Data.Monoid.Action where

import Data.Coerce
import Data.Semigroup

{- | * @mact mempty = id@
   * @mact (f <> g) = mact f . mact g@
-}
class (Monoid f) => MonoidAction f a where
  mact :: f -> a -> a

instance MonoidAction () m where
  mact :: () -> m -> m
mact = (m -> m) -> () -> m -> m
forall a b. a -> b -> a
const m -> m
forall a. a -> a
id
  {-# INLINE mact #-}

instance (Monoid m) => MonoidAction m m where
  mact :: m -> m -> m
mact = m -> m -> m
forall a. Semigroup a => a -> a -> a
(<>)
  {-# INLINE mact #-}

instance (Num a) => MonoidAction (Sum a) a where
  mact :: Sum a -> a -> a
mact = (a -> a -> a) -> Sum a -> a -> a
forall a b. Coercible a b => a -> b
coerce (forall a. Num a => a -> a -> a
(+) @a)
  {-# INLINE mact #-}

instance (Num a) => MonoidAction (Product a) a where
  mact :: Product a -> a -> a
mact = (a -> a -> a) -> Product a -> a -> a
forall a b. Coercible a b => a -> b
coerce (forall a. Num a => a -> a -> a
(*) @a)
  {-# INLINE mact #-}

instance (Num a) => MonoidAction (Product a) (Sum a) where
  mact :: Product a -> Sum a -> Sum a
mact = (a -> a -> a) -> Product a -> Sum a -> Sum a
forall a b. Coercible a b => a -> b
coerce (forall a. Num a => a -> a -> a
(*) @a)
  {-# INLINE mact #-}

instance (Ord a, Bounded a) => MonoidAction (Max a) a where
  mact :: Max a -> a -> a
mact = (a -> a -> a) -> Max a -> a -> a
forall a b. Coercible a b => a -> b
coerce (forall a. Ord a => a -> a -> a
max @a)
  {-# INLINE mact #-}

instance (Ord a, Bounded a) => MonoidAction (Min a) a where
  mact :: Min a -> a -> a
mact = (a -> a -> a) -> Min a -> a -> a
forall a b. Coercible a b => a -> b
coerce (forall a. Ord a => a -> a -> a
min @a)
  {-# INLINE mact #-}