{-# LANGUAGE PatternSynonyms #-}

-- | One-shot endomorphisms
--   Mostly for backwards compatibility.

-- One-shot endomorphisms
-- Like GHC.Internal.Data.Semigroup.Internal.Endo, but using
-- the one-shot trick from
--    Note [The one-shot state monad trick] in  GHC.Utils.Monad.

module GHC.Utils.EndoOS( EndoOS(EndoOS, appEndoOS ) ) where

import GHC.Prelude

import Data.Semigroup
import GHC.Exts (oneShot)

newtype EndoOS a = EndoOS' { forall a. EndoOS a -> a -> a
appEndoOS :: a -> a }


instance Semigroup (EndoOS a) where
  EndoOS a
f <> :: EndoOS a -> EndoOS a -> EndoOS a
<> EndoOS a
g = (a -> a) -> EndoOS a
forall a. (a -> a) -> EndoOS a
EndoOS (EndoOS a -> a -> a
forall a. EndoOS a -> a -> a
appEndoOS EndoOS a
f (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EndoOS a -> a -> a
forall a. EndoOS a -> a -> a
appEndoOS EndoOS a
g)

instance Monoid (EndoOS a) where
   mempty :: EndoOS a
mempty  = (a -> a) -> EndoOS a
forall a. (a -> a) -> EndoOS a
EndoOS a -> a
forall a. a -> a
id

pattern EndoOS :: (a->a) -> EndoOS a
pattern $mEndoOS :: forall {r} {a}. EndoOS a -> ((a -> a) -> r) -> ((# #) -> r) -> r
$bEndoOS :: forall a. (a -> a) -> EndoOS a
EndoOS f <- EndoOS' f
      where
        EndoOS a -> a
f = (a -> a) -> EndoOS a
forall a. (a -> a) -> EndoOS a
EndoOS' ((a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
oneShot a -> a
f)
         -- oneShot: this is the core of the one-shot trick!
         -- Note [The one-shot state monad trick] in  GHC.Utils.Monad.