endo-0.2.0.1: src/Data/Monoid/Endo.hs
{-# LANGUAGE NoImplicitPrelude #-}
-- |
-- Module: $HEADER$
-- Description: Utilities for Endo data type.
-- Copyright: (c) 2013-2015, Peter Trško
-- License: BSD3
--
-- Maintainer: peter.trsko@gmail.com
-- Stability: experimental
-- Portability: NoImplicitPrelude
--
-- Utilities for 'Endo' data type from "Data.Monoid" module.
module Data.Monoid.Endo
(
-- * Endo
E
, Endo(..)
, runEndo
, mapEndo
, mapEndo2
, liftEndo
-- * Lens
, endo
)
where
import Data.Functor (Functor(fmap))
import Data.Monoid (Endo(..))
import Data.Function.Between ((~@~), (<~@~))
-- | Type synonym for endomorphsm; it can be used to simplify type signatures.
type E a = a -> a
-- | Transform function wrapped in 'Endo'.
mapEndo :: (E a -> E b) -> Endo a -> Endo b
mapEndo = Endo ~@~ appEndo
{-# INLINE mapEndo #-}
-- | Variation of 'mapEndo' for functions with arity two.
mapEndo2 :: (E a -> E b -> E c) -> Endo a -> Endo b -> Endo c
mapEndo2 = mapEndo ~@~ appEndo
{-# INLINE mapEndo2 #-}
-- | Apply 'fmap' to function wrapped in 'Endo'. It's a short hand for
-- @'mapEndo' 'fmap'@.
liftEndo :: Functor f => Endo a -> Endo (f a)
liftEndo (Endo f) = Endo (fmap f)
{-# INLINE liftEndo #-}
-- | Flipped version of 'appEndo'.
runEndo :: a -> Endo a -> a
runEndo x (Endo f) = f x
{-# INLINE runEndo #-}
-- | Lens for 'Endo'. In terms of /lens/ package it would have type:
--
-- @
-- 'endo' :: Lens ('Endo' a) ('Endo' b) ('E' a) ('E' b)
-- @
--
-- For details see <http://hackage.haskell.org/package/lens lens package>.
endo :: Functor f => (E a -> f (E b)) -> Endo a -> f (Endo b)
endo = Endo <~@~ appEndo
{-# INLINE endo #-}