    {-# LANGUAGE
        DataKinds,
        PolyKinds,
        TypeFamilies,
        TypeOperators,
        UndecidableInstances #-}

    -- | Carriers of useful monoid instances.
    module Fcf.Class.Monoid.Types
      ( -- * Endo
        Endo(..)
      , UnEndo
      ) where

    import Fcf.Core (Exp)
    import Fcf.Combinators (Pure, type (<=<))
    import Fcf.Class.Monoid

    -- | Endofunctions.
    --
    -- === __Details__
    --
    -- This is is used in the default implementation of
    -- 'Fcf.Class.Foldable.Foldr' in terms of
    -- 'Fcf.Class.Foldable.FoldMap'.
    newtype Endo a = Endo (a -> Exp a)

    -- | Inverse of the 'Endo' constructor.
    type family UnEndo (e :: Endo a) :: a -> Exp a where
      UnEndo ('Endo f) = f

    -- * Endo as a monoid
    --
    -- Note it is only a monoid up to 'Eval'.

    type instance 'Endo f <> 'Endo g = 'Endo (f <=< g)
    type instance MEmpty = 'Endo Pure