    {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE CPP #-}
    #if __GLASGOW_HASKELL__ >= 702
    {-# LANGUAGE Trustworthy #-}
    #endif

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Data.Semigroup.Self
    -- Copyright   :  (c) Edward Kmett 2009
    -- License     :  BSD-style
    -- Maintainer  :  ekmett@gmail.com
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- A simple 'Monoid' transformer that takes a 'Monoid' m and produces a new @m@-Reducer named 'Self' @m@
    --
    -- This is useful when you have a generator that already contains monoidal values or someone supplies
    -- the map to the monoid in the form of a function rather than as a "Reducer" instance. You can just
    -- @'getSelf' . `reduce`@ or @'getSelf' . 'mapReduce' f@ in those scenarios. These behaviors are encapsulated
    -- into the 'fold' and 'foldMap' combinators in "Data.Monoid.Combinators" respectively.
    --
    -----------------------------------------------------------------------------

    module Data.Semigroup.Self
        ( Self(..)
        )  where

    #if __GLASGOW_HASKELL__ < 710
    import Control.Applicative
    import Data.Foldable
    import Data.Traversable
    #endif
    #if !(MIN_VERSION_base(4,11,0))
    import Data.Semigroup
    #endif
    import Data.Semigroup.Foldable
    import Data.Semigroup.Traversable
    import Data.Semigroup.Reducer (Reducer(..))

    newtype Self m = Self { getSelf :: m } deriving (Semigroup, Monoid)

    instance Semigroup m => Reducer m (Self m) where
      unit = Self

    instance Functor Self where
      fmap f (Self x) = Self (f x)

    instance Foldable Self where
      foldMap f (Self x) = f x

    instance Traversable Self where
      traverse f (Self x) = Self <$> f x

    instance Foldable1 Self where
      foldMap1 f (Self x) = f x

    instance Traversable1 Self where
      traverse1 f (Self x) = Self <$> f x