endo-0.3.0.0: Endomorphism utilities.

Copyright(c) 2014-2016 Peter Trško
LicenseBSD3
Maintainerpeter.trsko@gmail.com
Stabilityexperimental
PortabilityCPP, DeriveDataTypeable, DeriveGeneric, FlexibleInstances, NoImplicitPrelude, TypeFamilies
Safe HaskellNone
LanguageHaskell2010

Data.Monoid.Endo.AnEndo

Contents

Description

Conversion of values in to endomorphisms.

Synopsis

Conversion Into Endo

Various types can be interpreted as an encoding of an endomorphism. In example, enum can be viewed as family of endomorphisms where each sets a specific field of a record to a specific enum value, i.e. data constructor. Type class AnEndo provides generic way to convert values in to an endomorphism using anEndo and aDualEndo functions.

class AnEndo a where Source #

Class that represents various endomorphism representation. In other words anything that encodes (a -> a) can be instance of this class.

Here are some important instances with not so obvious definitions.

instance AnEndo (Proxy a) where
    type EndoOperatesOn (Proxy a) = a

    anEndo    _ = mempty -- = Endo id
    aDualEndo _ = mempty

It got quite common to use Proxy data type as an explicit way to pass types around. Above instance allows you to restrict type of result of endomorphism folding, to some extent.

instance AnEndo a => AnEndo (Maybe a) where
    type EndoOperatesOn (Maybe a) = EndoOperatesOn a

    anEndo Nothing  = mempty -- = Endo id
    anEndo (Just e) = anEndo e

    -- Definition of aDualEndo is analogous.

Instance for Maybe lets us conditionally inject endomorphism in to a folding chain.

instance AnEndo a => AnEndo (Identity a) where
    type EndoOperatesOn (Identity a) = EndoOperatesOn a

    anEndo (Identity e) = anEndo e
    aDualEndo (Identity e) = aDualEndo e

Above instance allows us to discard Identity wrapper, which is commonly used in data types that are parametrized by functor or monad.

Minimal complete definition

anEndo | aDualEndo

Associated Types

type EndoOperatesOn a Source #

Extract type on which endomorphism operates, e.g. for (Endo a) it would be a.

Methods

anEndo :: a -> Endo (EndoOperatesOn a) Source #

Convert value encoding (a -> a) in to Endo. Default implementation:

anEndo = getDual . aDualEndo

aDualEndo :: a -> Dual (Endo (EndoOperatesOn a)) Source #

Dual to anEndo. Default implementation:

aDualEndo = Dual . anEndo

Instances

AnEndo a => AnEndo [a] Source # 

Associated Types

type EndoOperatesOn [a] :: * Source #

Methods

anEndo :: [a] -> Endo (EndoOperatesOn [a]) Source #

aDualEndo :: [a] -> Dual (Endo (EndoOperatesOn [a])) Source #

AnEndo a => AnEndo (Maybe a) Source # 

Associated Types

type EndoOperatesOn (Maybe a) :: * Source #

AnEndo a => AnEndo (Identity a) Source # 
AnEndo a => AnEndo (Option a) Source #

Has same semantics as Maybe and it is actually defined in terms of AnEndo instance for Maybe.

Associated Types

type EndoOperatesOn (Option a) :: * Source #

AnEndo (Endo a) Source # 

Associated Types

type EndoOperatesOn (Endo a) :: * Source #

AnEndo (a -> a) Source # 

Associated Types

type EndoOperatesOn (a -> a) :: * Source #

Methods

anEndo :: (a -> a) -> Endo (EndoOperatesOn (a -> a)) Source #

aDualEndo :: (a -> a) -> Dual (Endo (EndoOperatesOn (a -> a))) Source #

(AnEndo a, AnEndo b, (~) * (EndoOperatesOn a) (EndoOperatesOn b)) => AnEndo (a, b) Source # 

Associated Types

type EndoOperatesOn (a, b) :: * Source #

Methods

anEndo :: (a, b) -> Endo (EndoOperatesOn (a, b)) Source #

aDualEndo :: (a, b) -> Dual (Endo (EndoOperatesOn (a, b))) Source #

AnEndo (Proxy * a) Source #

Constructs identity endomorphism for specified phantom type.

Associated Types

type EndoOperatesOn (Proxy * a) :: * Source #

(Foldable f, AnEndo a) => AnEndo (WrappedFoldable f a) Source # 
(AnEndo a, AnEndo b, AnEndo c, (~) * (EndoOperatesOn a) (EndoOperatesOn b), (~) * (EndoOperatesOn a) (EndoOperatesOn c)) => AnEndo (a, b, c) Source # 

Associated Types

type EndoOperatesOn (a, b, c) :: * Source #

Methods

anEndo :: (a, b, c) -> Endo (EndoOperatesOn (a, b, c)) Source #

aDualEndo :: (a, b, c) -> Dual (Endo (EndoOperatesOn (a, b, c))) Source #

(Foldable f, AnEndo a) => AnEndo (Reverse * f a) Source #

Fold in reverese order.

Associated Types

type EndoOperatesOn (Reverse * f a) :: * Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4)) => AnEndo (a1, a2, a3, a4) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4) -> Endo (EndoOperatesOn (a1, a2, a3, a4)) Source #

aDualEndo :: (a1, a2, a3, a4) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4))) Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, AnEndo a5, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4), (~) * (EndoOperatesOn a1) (EndoOperatesOn a5)) => AnEndo (a1, a2, a3, a4, a5) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4, a5) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4, a5) -> Endo (EndoOperatesOn (a1, a2, a3, a4, a5)) Source #

aDualEndo :: (a1, a2, a3, a4, a5) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4, a5))) Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, AnEndo a5, AnEndo a6, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4), (~) * (EndoOperatesOn a1) (EndoOperatesOn a5), (~) * (EndoOperatesOn a1) (EndoOperatesOn a6)) => AnEndo (a1, a2, a3, a4, a5, a6) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4, a5, a6) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4, a5, a6) -> Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6)) Source #

aDualEndo :: (a1, a2, a3, a4, a5, a6) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6))) Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, AnEndo a5, AnEndo a6, AnEndo a7, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4), (~) * (EndoOperatesOn a1) (EndoOperatesOn a5), (~) * (EndoOperatesOn a1) (EndoOperatesOn a6), (~) * (EndoOperatesOn a1) (EndoOperatesOn a7)) => AnEndo (a1, a2, a3, a4, a5, a6, a7) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4, a5, a6, a7) -> Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7)) Source #

aDualEndo :: (a1, a2, a3, a4, a5, a6, a7) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7))) Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, AnEndo a5, AnEndo a6, AnEndo a7, AnEndo a8, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4), (~) * (EndoOperatesOn a1) (EndoOperatesOn a5), (~) * (EndoOperatesOn a1) (EndoOperatesOn a6), (~) * (EndoOperatesOn a1) (EndoOperatesOn a7), (~) * (EndoOperatesOn a1) (EndoOperatesOn a8)) => AnEndo (a1, a2, a3, a4, a5, a6, a7, a8) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4, a5, a6, a7, a8) -> Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8)) Source #

aDualEndo :: (a1, a2, a3, a4, a5, a6, a7, a8) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8))) Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, AnEndo a5, AnEndo a6, AnEndo a7, AnEndo a8, AnEndo a9, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4), (~) * (EndoOperatesOn a1) (EndoOperatesOn a5), (~) * (EndoOperatesOn a1) (EndoOperatesOn a6), (~) * (EndoOperatesOn a1) (EndoOperatesOn a7), (~) * (EndoOperatesOn a1) (EndoOperatesOn a8), (~) * (EndoOperatesOn a1) (EndoOperatesOn a9)) => AnEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4, a5, a6, a7, a8, a9) -> Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9)) Source #

aDualEndo :: (a1, a2, a3, a4, a5, a6, a7, a8, a9) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9))) Source #

(AnEndo a1, AnEndo a2, AnEndo a3, AnEndo a4, AnEndo a5, AnEndo a6, AnEndo a7, AnEndo a8, AnEndo a9, AnEndo a10, (~) * (EndoOperatesOn a1) (EndoOperatesOn a2), (~) * (EndoOperatesOn a1) (EndoOperatesOn a3), (~) * (EndoOperatesOn a1) (EndoOperatesOn a4), (~) * (EndoOperatesOn a1) (EndoOperatesOn a5), (~) * (EndoOperatesOn a1) (EndoOperatesOn a6), (~) * (EndoOperatesOn a1) (EndoOperatesOn a7), (~) * (EndoOperatesOn a1) (EndoOperatesOn a8), (~) * (EndoOperatesOn a1) (EndoOperatesOn a9), (~) * (EndoOperatesOn a1) (EndoOperatesOn a10)) => AnEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) Source # 

Associated Types

type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) :: * Source #

Methods

anEndo :: (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) -> Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)) Source #

aDualEndo :: (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) -> Dual (Endo (EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10))) Source #

WrappedFoldable

Newtype WrappedFoldable allows us to use anEndo, aDualEndo, foldEndo, and dualFoldEndo for any Foldable instance without the need to create specific instance for that specific Foldable type and reduces. It would be possible to create AnEndo instance for all Foldable types, but that would require OverlappingInstances language extension.

Usage examples:

\vectorOfEndos -> anEndo (WrappedFoldable vectorOfEndos)
    :: Vector (E a) -> Endo a
\vectorOfEndos -> foldEndo (WrappedFoldable vectorOfEndos)
    :: FoldEndoArgs => Vector (E a) -> args

Note that the Vector is just one of possible Foldable data types that may be used here. Also, (E a) is just an example of endomorphism representation, any AnEndo instance can be used.

newtype WrappedFoldable f a Source #

Wrapper for Foldable types. Used to provide instances that work for all Foldable types without the need for OverlappingInstances language extension.

Constructors

WrapFoldable 

Fields

Instances

Monad f => Monad (WrappedFoldable f) Source # 
Functor f => Functor (WrappedFoldable f) Source # 

Methods

fmap :: (a -> b) -> WrappedFoldable f a -> WrappedFoldable f b #

(<$) :: a -> WrappedFoldable f b -> WrappedFoldable f a #

Applicative f => Applicative (WrappedFoldable f) Source # 
Foldable f => Foldable (WrappedFoldable f) Source # 

Methods

fold :: Monoid m => WrappedFoldable f m -> m #

foldMap :: Monoid m => (a -> m) -> WrappedFoldable f a -> m #

foldr :: (a -> b -> b) -> b -> WrappedFoldable f a -> b #

foldr' :: (a -> b -> b) -> b -> WrappedFoldable f a -> b #

foldl :: (b -> a -> b) -> b -> WrappedFoldable f a -> b #

foldl' :: (b -> a -> b) -> b -> WrappedFoldable f a -> b #

foldr1 :: (a -> a -> a) -> WrappedFoldable f a -> a #

foldl1 :: (a -> a -> a) -> WrappedFoldable f a -> a #

toList :: WrappedFoldable f a -> [a] #

null :: WrappedFoldable f a -> Bool #

length :: WrappedFoldable f a -> Int #

elem :: Eq a => a -> WrappedFoldable f a -> Bool #

maximum :: Ord a => WrappedFoldable f a -> a #

minimum :: Ord a => WrappedFoldable f a -> a #

sum :: Num a => WrappedFoldable f a -> a #

product :: Num a => WrappedFoldable f a -> a #

Traversable f => Traversable (WrappedFoldable f) Source # 

Methods

traverse :: Applicative f => (a -> f b) -> WrappedFoldable f a -> f (WrappedFoldable f b) #

sequenceA :: Applicative f => WrappedFoldable f (f a) -> f (WrappedFoldable f a) #

mapM :: Monad m => (a -> m b) -> WrappedFoldable f a -> m (WrappedFoldable f b) #

sequence :: Monad m => WrappedFoldable f (m a) -> m (WrappedFoldable f a) #

Generic1 (WrappedFoldable f) Source # 

Associated Types

type Rep1 (WrappedFoldable f :: * -> *) :: * -> * #

Eq1 f => Eq1 (WrappedFoldable f) Source # 

Methods

liftEq :: (a -> b -> Bool) -> WrappedFoldable f a -> WrappedFoldable f b -> Bool #

Ord1 f => Ord1 (WrappedFoldable f) Source # 

Methods

liftCompare :: (a -> b -> Ordering) -> WrappedFoldable f a -> WrappedFoldable f b -> Ordering #

Read1 f => Read1 (WrappedFoldable f) Source # 

Methods

liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (WrappedFoldable f a) #

liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [WrappedFoldable f a] #

Show1 f => Show1 (WrappedFoldable f) Source # 

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> WrappedFoldable f a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [WrappedFoldable f a] -> ShowS #

(Data (f a), Typeable * a, Typeable (* -> *) f) => Data (WrappedFoldable f a) Source # 

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> WrappedFoldable f a -> c (WrappedFoldable f a) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (WrappedFoldable f a) #

toConstr :: WrappedFoldable f a -> Constr #

dataTypeOf :: WrappedFoldable f a -> DataType #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (WrappedFoldable f a)) #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (WrappedFoldable f a)) #

gmapT :: (forall b. Data b => b -> b) -> WrappedFoldable f a -> WrappedFoldable f a #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> WrappedFoldable f a -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> WrappedFoldable f a -> r #

gmapQ :: (forall d. Data d => d -> u) -> WrappedFoldable f a -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> WrappedFoldable f a -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> WrappedFoldable f a -> m (WrappedFoldable f a) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> WrappedFoldable f a -> m (WrappedFoldable f a) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> WrappedFoldable f a -> m (WrappedFoldable f a) #

Read (f a) => Read (WrappedFoldable f a) Source # 
Show (f a) => Show (WrappedFoldable f a) Source # 
Generic (WrappedFoldable f a) Source # 

Associated Types

type Rep (WrappedFoldable f a) :: * -> * #

Methods

from :: WrappedFoldable f a -> Rep (WrappedFoldable f a) x #

to :: Rep (WrappedFoldable f a) x -> WrappedFoldable f a #

(Foldable f, AnEndo a) => AnEndo (WrappedFoldable f a) Source # 
type Rep1 (WrappedFoldable f) Source # 
type Rep1 (WrappedFoldable f) = D1 (MetaData "WrappedFoldable" "Data.Monoid.Endo.AnEndo" "endo-0.3.0.0-FDoQmRwl62o5XNvfgqOehr" True) (C1 (MetaCons "WrapFoldable" PrefixI True) (S1 (MetaSel (Just Symbol "getFoldable") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec1 f)))
type Rep (WrappedFoldable f a) Source # 
type Rep (WrappedFoldable f a) = D1 (MetaData "WrappedFoldable" "Data.Monoid.Endo.AnEndo" "endo-0.3.0.0-FDoQmRwl62o5XNvfgqOehr" True) (C1 (MetaCons "WrapFoldable" PrefixI True) (S1 (MetaSel (Just Symbol "getFoldable") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (f a))))
type EndoOperatesOn (WrappedFoldable f a) Source # 

Utility Functions and Types

embedEndoWith Source #

Arguments

:: (AnEndo e, EndoOperatesOn e ~ a) 
=> (Endo a -> b)

Embedding function.

-> e 
-> b 

Use Endo (possibly result of foldEndo) and use it to create value of different type.

Examples:

embedEndoWith tell
    :: (Monad m, AnEndo e, w ~ EndoOperatesOn e)
    => e
    -> WriterT (Endo w) m ()

embedEndoWith (modify . appEndo)
    :: (Monad m, AnEndo e, s ~ EndoOperatesOn e)
    => e
    -> StateT s m ()

See also embedDualEndoWith.

embedDualEndoWith Source #

Arguments

:: (AnEndo e, EndoOperatesOn e ~ a) 
=> (Dual (Endo a) -> b)

Embedding function.

-> e 
-> b 

Dual to embedEndoWith, which uses aDualEndo instead of anEndo.