endo 0.2.0.1 → 0.3.0.0
raw patch · 10 files changed
+1499/−508 lines, 10 filesdep +data-default-classdep +mtlPVP ok
version bump matches the API change (PVP)
Dependencies added: data-default-class, mtl
API changes (from Hackage documentation)
- Data.Monoid.Endo: appEndo :: Endo a -> a -> a
- Data.Monoid.Endo.Fold: getFoldable :: WrappedFoldable f a -> f a
- Data.Monoid.Endo.Fold: instance (AnEndo a, AnEndo b, AnEndo c, EndoOperatesOn a ~ EndoOperatesOn b, EndoOperatesOn a ~ EndoOperatesOn c) => AnEndo (a, b, c)
- Data.Monoid.Endo.Fold: instance (AnEndo a, AnEndo b, EndoOperatesOn a ~ EndoOperatesOn b) => AnEndo (a, b)
- Data.Monoid.Endo.Fold: instance (AnEndo a, FoldEndoArgs r, EndoOperatesOn a ~ ResultOperatesOn r) => FoldEndoArgs (a -> r)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (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)
- Data.Monoid.Endo.Fold: instance (Applicative f, Applicative g, FoldEndoArgs r) => FoldEndoArgs (Compose f g r)
- Data.Monoid.Endo.Fold: instance (Applicative f, Applicative g, FoldEndoArgs r) => FoldEndoArgs (Product f g r)
- Data.Monoid.Endo.Fold: instance (Applicative f, FoldEndoArgs r) => FoldEndoArgs (IdentityT f r)
- Data.Monoid.Endo.Fold: instance (Applicative f, FoldEndoArgs r) => FoldEndoArgs (ListT f r)
- Data.Monoid.Endo.Fold: instance (Applicative f, FoldEndoArgs r) => FoldEndoArgs (ReaderT r' f r)
- Data.Monoid.Endo.Fold: instance (Applicative f, FoldEndoArgs r, Monoid w) => FoldEndoArgs (WriterT w f r)
- Data.Monoid.Endo.Fold: instance (Data (f a), Typeable f, Typeable a) => Data (WrappedFoldable f a)
- Data.Monoid.Endo.Fold: instance (Foldable f, AnEndo a) => AnEndo (Reverse f a)
- Data.Monoid.Endo.Fold: instance (Foldable f, AnEndo a) => AnEndo (WrappedFoldable f a)
- Data.Monoid.Endo.Fold: instance (Monad m, FoldEndoArgs r) => FoldEndoArgs (StateT s m r)
- Data.Monoid.Endo.Fold: instance (Monad m, Functor m, FoldEndoArgs r) => FoldEndoArgs (MaybeT m r)
- Data.Monoid.Endo.Fold: instance (Monad m, Functor m, Monoid w, FoldEndoArgs r) => FoldEndoArgs (RWST r' w s m r)
- Data.Monoid.Endo.Fold: instance (Monoid c, FoldEndoArgs r) => FoldEndoArgs (Const c r)
- Data.Monoid.Endo.Fold: instance AnEndo (Endo a)
- Data.Monoid.Endo.Fold: instance AnEndo (Proxy a)
- Data.Monoid.Endo.Fold: instance AnEndo (a -> a)
- Data.Monoid.Endo.Fold: instance AnEndo a => AnEndo (Maybe a)
- Data.Monoid.Endo.Fold: instance AnEndo a => AnEndo [a]
- Data.Monoid.Endo.Fold: instance Constructor C1_0WrappedFoldable
- Data.Monoid.Endo.Fold: instance Datatype D1WrappedFoldable
- Data.Monoid.Endo.Fold: instance FoldEndoArgs (Endo a)
- Data.Monoid.Endo.Fold: instance FoldEndoArgs r => FoldEndoArgs (Either e r)
- Data.Monoid.Endo.Fold: instance FoldEndoArgs r => FoldEndoArgs (IO r)
- Data.Monoid.Endo.Fold: instance FoldEndoArgs r => FoldEndoArgs (Identity r)
- Data.Monoid.Endo.Fold: instance FoldEndoArgs r => FoldEndoArgs (Maybe r)
- Data.Monoid.Endo.Fold: instance Generic (WrappedFoldable f a)
- Data.Monoid.Endo.Fold: instance Read (f a) => Read (WrappedFoldable f a)
- Data.Monoid.Endo.Fold: instance Selector S1_0_0WrappedFoldable
- Data.Monoid.Endo.Fold: instance Show (f a) => Show (WrappedFoldable f a)
- Data.Monoid.Endo.Fold: instance Typeable WrappedFoldable
+ Data.Monoid.Endo: [appEndo] :: Endo a -> a -> a
+ Data.Monoid.Endo.AnEndo: WrapFoldable :: f a -> WrappedFoldable f a
+ Data.Monoid.Endo.AnEndo: [getFoldable] :: WrappedFoldable f a -> f a
+ Data.Monoid.Endo.AnEndo: aDualEndo :: AnEndo a => a -> Dual (Endo (EndoOperatesOn a))
+ Data.Monoid.Endo.AnEndo: anEndo :: AnEndo a => a -> Endo (EndoOperatesOn a)
+ Data.Monoid.Endo.AnEndo: class AnEndo a where type EndoOperatesOn a anEndo = getDual . aDualEndo aDualEndo = Dual . anEndo where {
+ Data.Monoid.Endo.AnEndo: embedDualEndoWith :: (AnEndo e, EndoOperatesOn e ~ a) => (Dual (Endo a) -> b) -> e -> b
+ Data.Monoid.Endo.AnEndo: embedEndoWith :: (AnEndo e, EndoOperatesOn e ~ a) => (Endo a -> b) -> e -> b
+ Data.Monoid.Endo.AnEndo: instance (Data.Data.Data (f a), Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable f) => Data.Data.Data (Data.Monoid.Endo.AnEndo.WrappedFoldable f a)
+ Data.Monoid.Endo.AnEndo: instance (Data.Foldable.Foldable f, Data.Monoid.Endo.AnEndo.AnEndo a) => Data.Monoid.Endo.AnEndo.AnEndo (Data.Functor.Reverse.Reverse f a)
+ Data.Monoid.Endo.AnEndo: instance (Data.Foldable.Foldable f, Data.Monoid.Endo.AnEndo.AnEndo a) => Data.Monoid.Endo.AnEndo.AnEndo (Data.Monoid.Endo.AnEndo.WrappedFoldable f a)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a, Data.Monoid.Endo.AnEndo.AnEndo b, Data.Monoid.Endo.AnEndo.AnEndo c, Data.Monoid.Endo.AnEndo.EndoOperatesOn a ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn b, Data.Monoid.Endo.AnEndo.EndoOperatesOn a ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn c) => Data.Monoid.Endo.AnEndo.AnEndo (a, b, c)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a, Data.Monoid.Endo.AnEndo.AnEndo b, Data.Monoid.Endo.AnEndo.EndoOperatesOn a ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn b) => Data.Monoid.Endo.AnEndo.AnEndo (a, b)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.AnEndo a5, Data.Monoid.Endo.AnEndo.AnEndo a6, Data.Monoid.Endo.AnEndo.AnEndo a7, Data.Monoid.Endo.AnEndo.AnEndo a8, Data.Monoid.Endo.AnEndo.AnEndo a9, Data.Monoid.Endo.AnEndo.AnEndo a10, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a5, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a6, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a7, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a8, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a9, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a10) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.AnEndo a5, Data.Monoid.Endo.AnEndo.AnEndo a6, Data.Monoid.Endo.AnEndo.AnEndo a7, Data.Monoid.Endo.AnEndo.AnEndo a8, Data.Monoid.Endo.AnEndo.AnEndo a9, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a5, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a6, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a7, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a8, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a9) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.AnEndo a5, Data.Monoid.Endo.AnEndo.AnEndo a6, Data.Monoid.Endo.AnEndo.AnEndo a7, Data.Monoid.Endo.AnEndo.AnEndo a8, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a5, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a6, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a7, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a8) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4, a5, a6, a7, a8)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.AnEndo a5, Data.Monoid.Endo.AnEndo.AnEndo a6, Data.Monoid.Endo.AnEndo.AnEndo a7, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a5, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a6, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a7) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4, a5, a6, a7)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.AnEndo a5, Data.Monoid.Endo.AnEndo.AnEndo a6, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a5, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a6) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4, a5, a6)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.AnEndo a5, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a5) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4, a5)
+ Data.Monoid.Endo.AnEndo: instance (Data.Monoid.Endo.AnEndo.AnEndo a1, Data.Monoid.Endo.AnEndo.AnEndo a2, Data.Monoid.Endo.AnEndo.AnEndo a3, Data.Monoid.Endo.AnEndo.AnEndo a4, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a2, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a3, Data.Monoid.Endo.AnEndo.EndoOperatesOn a1 ~ Data.Monoid.Endo.AnEndo.EndoOperatesOn a4) => Data.Monoid.Endo.AnEndo.AnEndo (a1, a2, a3, a4)
+ Data.Monoid.Endo.AnEndo: instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance Data.Functor.Classes.Eq1 f => Data.Functor.Classes.Eq1 (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance Data.Functor.Classes.Ord1 f => Data.Functor.Classes.Ord1 (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance Data.Functor.Classes.Read1 f => Data.Functor.Classes.Read1 (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance Data.Functor.Classes.Show1 f => Data.Functor.Classes.Show1 (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo (Data.Monoid.Endo a)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo (Data.Proxy.Proxy a)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo (a -> a)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo a => Data.Monoid.Endo.AnEndo.AnEndo (Data.Functor.Identity.Identity a)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo a => Data.Monoid.Endo.AnEndo.AnEndo (Data.Semigroup.Option a)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo a => Data.Monoid.Endo.AnEndo.AnEndo (GHC.Base.Maybe a)
+ Data.Monoid.Endo.AnEndo: instance Data.Monoid.Endo.AnEndo.AnEndo a => Data.Monoid.Endo.AnEndo.AnEndo [a]
+ Data.Monoid.Endo.AnEndo: instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance GHC.Base.Applicative f => GHC.Base.Applicative (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance GHC.Base.Functor f => GHC.Base.Functor (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance GHC.Base.Monad f => GHC.Base.Monad (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance GHC.Generics.Generic (Data.Monoid.Endo.AnEndo.WrappedFoldable f a)
+ Data.Monoid.Endo.AnEndo: instance GHC.Generics.Generic1 (Data.Monoid.Endo.AnEndo.WrappedFoldable f)
+ Data.Monoid.Endo.AnEndo: instance GHC.Read.Read (f a) => GHC.Read.Read (Data.Monoid.Endo.AnEndo.WrappedFoldable f a)
+ Data.Monoid.Endo.AnEndo: instance GHC.Show.Show (f a) => GHC.Show.Show (Data.Monoid.Endo.AnEndo.WrappedFoldable f a)
+ Data.Monoid.Endo.AnEndo: newtype WrappedFoldable f a
+ Data.Monoid.Endo.AnEndo: type family EndoOperatesOn a;
+ Data.Monoid.Endo.AnEndo: }
+ Data.Monoid.Endo.Apply: ApplyEndo :: f a -> ApplyEndo t f a
+ Data.Monoid.Endo.Apply: [applyEndo] :: ApplyEndo t f a -> f a
+ Data.Monoid.Endo.Apply: apply :: Applicative f => a -> Endo a -> ApplyEndo t f a
+ Data.Monoid.Endo.Apply: applyDef :: (Applicative f, Default a) => ApplyEndo Def f a -> f a
+ Data.Monoid.Endo.Apply: applyDef_ :: Default a => ApplyEndo Def Identity a -> a
+ Data.Monoid.Endo.Apply: applyF :: Functor f => a -> f (Endo a) -> ApplyEndo t f a
+ Data.Monoid.Endo.Apply: applyMempty :: Monoid a => ApplyEndo Mempty f a -> f a
+ Data.Monoid.Endo.Apply: applyMempty_ :: Monoid a => ApplyEndo Mempty Identity a -> a
+ Data.Monoid.Endo.Apply: applyModify :: MonadState s m => ApplyEndo Modify m s -> m s
+ Data.Monoid.Endo.Apply: applyModify' :: MonadState r m => ApplyEndo Modify' m () -> m ()
+ Data.Monoid.Endo.Apply: applyReader :: MonadReader r m => ApplyEndo Reader m r -> m r
+ Data.Monoid.Endo.Apply: applyReaderWith :: MonadReader r m => (m r -> a) -> ApplyEndo Reader m r -> a
+ Data.Monoid.Endo.Apply: data Def
+ Data.Monoid.Endo.Apply: data Mempty
+ Data.Monoid.Endo.Apply: data Modify
+ Data.Monoid.Endo.Apply: data Modify'
+ Data.Monoid.Endo.Apply: data Reader
+ Data.Monoid.Endo.Apply: instance (Data.Data.Data (f a), Data.Typeable.Internal.Typeable a, Data.Typeable.Internal.Typeable t, Data.Typeable.Internal.Typeable f) => Data.Data.Data (Data.Monoid.Endo.Apply.ApplyEndo t f a)
+ Data.Monoid.Endo.Apply: instance (GHC.Base.Applicative f, Data.Default.Class.Default a) => Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Endo.Apply.ApplyEndo Data.Monoid.Endo.Apply.Def f a)
+ Data.Monoid.Endo.Apply: instance (GHC.Base.Applicative f, GHC.Base.Monoid a) => Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Endo.Apply.ApplyEndo Data.Monoid.Endo.Apply.Mempty f a)
+ Data.Monoid.Endo.Apply: instance Control.Monad.Reader.Class.MonadReader r m => Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Endo.Apply.ApplyEndo Data.Monoid.Endo.Apply.Reader m r)
+ Data.Monoid.Endo.Apply: instance Control.Monad.State.Class.MonadState s m => Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Endo.Apply.ApplyEndo Data.Monoid.Endo.Apply.Modify m s)
+ Data.Monoid.Endo.Apply: instance Control.Monad.State.Class.MonadState s m => Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Endo.Apply.ApplyEndo Data.Monoid.Endo.Apply.Modify' m s)
+ Data.Monoid.Endo.Apply: instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance Data.Functor.Classes.Eq1 f => Data.Functor.Classes.Eq1 (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance Data.Functor.Classes.Ord1 f => Data.Functor.Classes.Ord1 (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance Data.Functor.Classes.Read1 f => Data.Functor.Classes.Read1 (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance Data.Functor.Classes.Show1 f => Data.Functor.Classes.Show1 (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance GHC.Base.Applicative f => GHC.Base.Applicative (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance GHC.Base.Functor f => GHC.Base.Functor (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance GHC.Base.Monad f => GHC.Base.Monad (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic (Data.Monoid.Endo.Apply.ApplyEndo t f a)
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic Data.Monoid.Endo.Apply.Def
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic Data.Monoid.Endo.Apply.Mempty
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic Data.Monoid.Endo.Apply.Modify
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic Data.Monoid.Endo.Apply.Modify'
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic Data.Monoid.Endo.Apply.Reader
+ Data.Monoid.Endo.Apply: instance GHC.Generics.Generic1 (Data.Monoid.Endo.Apply.ApplyEndo t f)
+ Data.Monoid.Endo.Apply: joinApplyDef :: (Monad m, Default a) => m (ApplyEndo Def m a) -> m a
+ Data.Monoid.Endo.Apply: joinApplyMempty :: (Monad m, Monoid a) => m (ApplyEndo Mempty m a) -> m a
+ Data.Monoid.Endo.Apply: joinApplyModify :: MonadState s m => m (ApplyEndo Modify m s) -> m s
+ Data.Monoid.Endo.Apply: joinApplyModify' :: MonadState r m => m (ApplyEndo Modify' m r) -> m r
+ Data.Monoid.Endo.Apply: joinApplyReader :: MonadReader r m => m (ApplyEndo Reader m r) -> m r
+ Data.Monoid.Endo.Apply: newtype ApplyEndo t f a
+ Data.Monoid.Endo.Fold: [getFoldable] :: WrappedFoldable f a -> f a
+ Data.Monoid.Endo.Fold: infixl 1 <&$>
+ Data.Monoid.Endo.Fold: instance (Data.Monoid.Endo.AnEndo.AnEndo a, Data.Monoid.Endo.Fold.FoldEndoArgs r, Data.Monoid.Endo.AnEndo.EndoOperatesOn a ~ Data.Monoid.Endo.Fold.ResultOperatesOn r) => Data.Monoid.Endo.Fold.FoldEndoArgs (a -> r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.Identity.IdentityT f r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.List.ListT f r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.Reader.ReaderT r' f r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, Data.Monoid.Endo.Fold.FoldEndoArgs r, GHC.Base.Monoid w) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.Writer.Lazy.WriterT w f r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, Data.Monoid.Endo.Fold.FoldEndoArgs r, GHC.Base.Monoid w) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.Writer.Strict.WriterT w f r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, GHC.Base.Applicative g, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Data.Functor.Compose.Compose f g r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Applicative f, GHC.Base.Applicative g, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Data.Functor.Product.Product f g r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monad m, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.Except.ExceptT e m r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monad m, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.Maybe.MaybeT m r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monad m, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.State.Lazy.StateT s m r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monad m, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.State.Strict.StateT s m r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monad m, GHC.Base.Monoid w, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.RWS.Lazy.RWST r' w s m r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monad m, GHC.Base.Monoid w, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Control.Monad.Trans.RWS.Strict.RWST r' w s m r)
+ Data.Monoid.Endo.Fold: instance (GHC.Base.Monoid c, Data.Monoid.Endo.Fold.FoldEndoArgs r) => Data.Monoid.Endo.Fold.FoldEndoArgs (Data.Functor.Const.Const c r)
+ Data.Monoid.Endo.Fold: instance Data.Monoid.Endo.Fold.FoldEndoArgs (Data.Monoid.Endo a)
+ Data.Monoid.Endo.Fold: instance Data.Monoid.Endo.Fold.FoldEndoArgs r => Data.Monoid.Endo.Fold.FoldEndoArgs (Data.Either.Either e r)
+ Data.Monoid.Endo.Fold: instance Data.Monoid.Endo.Fold.FoldEndoArgs r => Data.Monoid.Endo.Fold.FoldEndoArgs (Data.Functor.Identity.Identity r)
+ Data.Monoid.Endo.Fold: instance Data.Monoid.Endo.Fold.FoldEndoArgs r => Data.Monoid.Endo.Fold.FoldEndoArgs (GHC.Base.Maybe r)
+ Data.Monoid.Endo.Fold: instance Data.Monoid.Endo.Fold.FoldEndoArgs r => Data.Monoid.Endo.Fold.FoldEndoArgs (GHC.Types.IO r)
+ Data.Monoid.Endo.Fold: type (:->) args r = (Result args ~ r) => args
+ Data.Monoid.Endo.Fold: type family EndoOperatesOn a;
+ Data.Monoid.Endo.Fold: }
+ Data.Monoid.Endo.FromEndo: class FromEndo a where type EndoOperatedOn a fromDualEndo = fromEndo . getDual where {
+ Data.Monoid.Endo.FromEndo: fromDualEndo :: FromEndo a => Dual (Endo (EndoOperatedOn a)) -> a
+ Data.Monoid.Endo.FromEndo: fromDualEndoTo :: FromEndo a => Dual (Endo (EndoOperatedOn a)) -> proxy a -> a
+ Data.Monoid.Endo.FromEndo: fromDualEndoWith :: (FromEndo a, EndoOperatedOn a ~ c) => (a -> b) -> Dual (Endo c) -> b
+ Data.Monoid.Endo.FromEndo: fromDualEndoWithF :: (Functor f, FromEndo a, EndoOperatedOn a ~ c) => (f a -> b) -> f (Dual (Endo c)) -> b
+ Data.Monoid.Endo.FromEndo: fromEndo :: FromEndo a => Endo (EndoOperatedOn a) -> a
+ Data.Monoid.Endo.FromEndo: fromEndoTo :: FromEndo a => Endo (EndoOperatedOn a) -> proxy a -> a
+ Data.Monoid.Endo.FromEndo: fromEndoWith :: (FromEndo a, EndoOperatedOn a ~ c) => (a -> b) -> Endo c -> b
+ Data.Monoid.Endo.FromEndo: fromEndoWithF :: (Functor f, FromEndo a, EndoOperatedOn a ~ c) => (f a -> b) -> f (Endo c) -> b
+ Data.Monoid.Endo.FromEndo: instance (GHC.Base.Monoid w, GHC.Base.Monad f) => Data.Monoid.Endo.FromEndo.FromEndo (Control.Monad.Trans.RWS.Lazy.RWST r w s f ())
+ Data.Monoid.Endo.FromEndo: instance (GHC.Base.Monoid w, GHC.Base.Monad f) => Data.Monoid.Endo.FromEndo.FromEndo (Control.Monad.Trans.RWS.Strict.RWST r w s f ())
+ Data.Monoid.Endo.FromEndo: instance Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Endo a)
+ Data.Monoid.Endo.FromEndo: instance Data.Monoid.Endo.FromEndo.FromEndo (a -> a)
+ Data.Monoid.Endo.FromEndo: instance Data.Monoid.Endo.FromEndo.FromEndo e => Data.Monoid.Endo.FromEndo.FromEndo (Data.Monoid.Dual e)
+ Data.Monoid.Endo.FromEndo: instance GHC.Base.Monad f => Data.Monoid.Endo.FromEndo.FromEndo (Control.Monad.Trans.Reader.ReaderT r f r)
+ Data.Monoid.Endo.FromEndo: instance GHC.Base.Monad f => Data.Monoid.Endo.FromEndo.FromEndo (Control.Monad.Trans.State.Lazy.StateT s f ())
+ Data.Monoid.Endo.FromEndo: instance GHC.Base.Monad f => Data.Monoid.Endo.FromEndo.FromEndo (Control.Monad.Trans.State.Strict.StateT s f ())
+ Data.Monoid.Endo.FromEndo: type family EndoOperatedOn a;
+ Data.Monoid.Endo.FromEndo: }
- Data.Monoid.Endo.Fold: class AnEndo a where type family EndoOperatesOn a anEndo = getDual . aDualEndo aDualEndo = Dual . anEndo
+ Data.Monoid.Endo.Fold: class AnEndo a where type EndoOperatesOn a anEndo = getDual . aDualEndo aDualEndo = Dual . anEndo where {
- Data.Monoid.Endo.Fold: class FoldEndoArgs a where type family ResultOperatesOn a type family Result a
+ Data.Monoid.Endo.Fold: class FoldEndoArgs a where type ResultOperatesOn a type Result a where {
Files
- ChangeLog.md +41/−9
- LICENSE +1/−1
- README.md +45/−8
- endo.cabal +46/−11
- example/Example8.hs +58/−0
- example/Example9.hs +26/−0
- src/Data/Monoid/Endo/AnEndo.hs +616/−0
- src/Data/Monoid/Endo/Apply.hs +425/−0
- src/Data/Monoid/Endo/Fold.hs +47/−479
- src/Data/Monoid/Endo/FromEndo.hs +194/−0
ChangeLog.md view
@@ -1,6 +1,35 @@ # ChangeLog / ReleaseNotes +## Version 0.3.0.0++* Introducing type `:->` to simplify type signatures of endomorphism folding+ functions that restrict type of a result. (**new**)+* Type class `AnEndo` moved in to a separate module `Data.Monoid.Endo.AnEndo`.+ Definitions are reexported by `Data.Monoid.Endo.Fold`, therefore providing+ backward compatible API. (**change**)+* Introducing `instance AnEndo a => AnEndo (Identity a)`. (**new**)+* Introducing `FromEndo` type class for conversion of endomorphism in to a+ value. It is a dual to `AnEndo` type class. This type class resides in its+ own module `Data.Monoid.Endo.FromEndo`. (**new**)+* Introducing `ApplyEndo` newtype that provides easier endomorphism evaluation+ in cases when there is an "obvious" default value. This type has its own+ module `Data.Monoid.Endo.Apply` that also provides various helper functions+ and type class instances. (**new**)+* Providing `Eq1`, `Ord1`, `Read1` and `Show1` instances if built with+ [transformers package][transformers] >=0.5 or base >=4.9 (i.e. GHC+ >=8.0.1) is available. (**new**)+* Providing `Generic1` instance for `WrappedFoldable`. (**new**)+* Introducing `instance AnEndo a => AnEndo (Option a)`, but only when compiled+ with base >=4.9, since that is the first version of base which contains+ `Semigroup`. (**new**)+* Bumped upper bound of [transformers package][transformers] to include 0.5.\*+ versions. (**change**)+* Synchronized API documentation of `Data.Monoid.Endo.Fold` with README.+ (**trivial change**)+* Uploaded to [Hackage][]: <http://hackage.haskell.org/package/endo-0.3.0.0>++ ## Version 0.2.0.1 * API documentation ehancements and clarifications.@@ -14,13 +43,13 @@ * Default implementation for `anEndo` method of 'AnEndo' type class, which is now defined as: `anEndo = getDual . aDualEndo`. As a consequence it is now possible to define complete instances of `AnEndo` by providing either- `anEndo` or `aDualEndo`. (new, change)+ `anEndo` or `aDualEndo`. (**new**, **change**) * Introducing associated type `Result` to `FoldEndoArgs` type class. This allows result of the whole folding to be explicitly stated in a type- signature. (new, change)+ signature. (**new**, **change**) * Introducing functions `embedEndoWith` and `embedDualEndoWith`. Both can be used to simplify application of endomorphisms that are result of folding.- (new)+ (**new**) - `embedEndoWith :: (AnEndo e, EndoOperatesOn e ~ a) => (Endo a -> b) -> e -> b` - `embedDualEndoWith :: (AnEndo e, EndoOperatesOn e ~ a) => (Dual (Endo a)@@ -28,19 +57,19 @@ * Introducing `instance AnEndo (Proxy a)`, which is useful in cases when one needs to force constraint `EndoOperatesOn args ~ a` where `a` is the `a` from `Proxy a`. This is done by encoding value of `Proxy` in to identity- endomorphism that operates on specified type `a`. (new)+ endomorphism that operates on specified type `a`. (**new**) * Introducing `instance (Monoid c, FoldEndoArgs r) => FoldEndoArgs (Const c r)`, which is useful in cases when one needs to discard the computation and- return a constant instead. (new)+ return a constant instead. (**new**) * Bumping upper bounds on base and between, therefore it now builds on GHC 7.10- with base 4.8. (new)+ with base 4.8. (**new**) * Uploaded to [Hackage][]: <http://hackage.haskell.org/package/endo-0.2.0.0> ## Version 0.1.0.2 * Bugfix release.-* Bugfix: Unable to compile with transformers >= 0.4 (again).+* Bugfix: Unable to compile with [transformers][] >= 0.4 (again). * Minor documentation updates. * Uploaded to [Hackage][]: <http://hackage.haskell.org/package/endo-0.1.0.2> @@ -48,13 +77,13 @@ ## Version 0.1.0.1 * Bugfix release.-* Bugfix: Unable to compile with transformers >= 0.4.+* Bugfix: Unable to compile with [transformers][] >= 0.4. * Uploaded to [Hackage][]: <http://hackage.haskell.org/package/endo-0.1.0.1> ## Version 0.1.0.0 -* **This version doesn't work with transformers >= 0.4.**+* **This version doesn't work with [transformers][] >= 0.4.** * First public release. * Uploaded to [Hackage][]: <http://hackage.haskell.org/package/endo-0.1.0.0> @@ -63,6 +92,9 @@ [Hackage]: http://hackage.haskell.org/ "HackageDB (or just Hackage) is a collection of releases of Haskell packages."+[transformers]:+ https://hackage.haskell.org/package/transformers+ "Package transformers on Hackage." <!-- vim: filetype=markdown softtabstop=4 shiftwidth=4 expandtab
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2013-2015, Peter Trško+Copyright (c) 2013-2016, Peter Trško All rights reserved.
README.md view
@@ -15,6 +15,12 @@ ## Usage Examples +Examples in this section were taken from real live production code, but they+were tamed down a little.+++### Basic Idea+ Lets define simple application `Config` data type as: ````Haskell@@ -56,14 +62,20 @@ ```` Above example shows us that it is possible to modify `Config` as if it was a-monoid, but without actually having to state it as such. In practice it is-not always possible to define it as `Monoid` or at least a `Semigroup`. What-usually works are endomorphisms, like in this example.+monoid, but without actually having to state it as such. In practice it is not+always possible to define it as `Monoid`, or at least as a `Semigroup`.+Endomorphism are monoids under composition, therefore they are what usually+works in situations when the modified data type can not be instantiated as a+monoid. -Now, `FilePath` has one pathological case, and that is `""`. There is a lot of-ways to handle it. Here we will concentrate only few basic techniques to-illustrate versatility of our approach. +### Working With Corner Cases++In real applications corner cases arise quite easily, e.g. `FilePath` has one+pathological case, and that is `""`. There is a lot of ways to handle it. Here+we will concentrate only few basic techniques to illustrate versatility of our+approach.+ ````Haskell -- | Trying to set output file to \"\" will result in keeping original value. setOutputFile2 :: FilePath -> E Config@@ -88,7 +100,15 @@ &$ setVerbosity Annoying &$ setOutputFile3 "an.out.put" ````+Great thing about `Maybe` is the fact that it has `Alternative` and `MonadPlus`+instances. Using `guard` may simplify `setOutputFile3` in to definition like+following: +````Haskell+setOutputFile3':: FilePath -> Maybe (E Config)+setOutputFile3' fp = setOutputFile fp <$ guard (not (null fp))+````+ Following example uses common pattern of using `Either` as error reporting monad. This approach can be easily modified for arbitrary error reporting monad.@@ -109,9 +129,12 @@ constructor arguments and order of operations. Using `foldEndo` (and its dual `dualFoldEndo`) doesn't have this restriction. -Instead of setter functions one may want to use lenses (in terms of-[lens package][Hackage: lens]):+### Lenses +Instead of setter functions one may want to use lenses. In this example we use+types from [lens package][Hackage: lens], but definitions use function from+[between package][Hackage: between]:+ ````Haskell verbosity :: Lens' Config Verbosity verbosity = _verbosity ~@@^> \s b -> s{_verbosity = b}@@ -129,6 +152,8 @@ &$ outputFile .~ "an.out.put" ```` +### Other Usage+ Probably one of the most interesting things that can be done with this module is following: @@ -248,6 +273,12 @@ Pass additional warning flags to GHC. +License+-------++The BSD 3-Clause License, see [LICENSE][] file for details.++ ## Contributions Contributions, pull requests and bug reports are welcome! Please don't be@@ -255,6 +286,9 @@ +[Hackage: between]:+ http://hackage.haskell.org/package/between+ "between package on Hackage" [Hackage: endo]: http://hackage.haskell.org/package/endo "endo package on Hackage"@@ -267,6 +301,9 @@ [Haskell.org]: http://www.haskell.org "The Haskell Programming Language"+[LICENSE]:+ https://github.com/trskop/endo/blob/master/LICENSE+ "License of endo package." [tl;dr Legal: BSD3]: https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29 "BSD 3-Clause License (Revised)"
endo.cabal view
@@ -1,5 +1,5 @@ name: endo-version: 0.2.0.1+version: 0.3.0.0 synopsis: Endomorphism utilities. description: Package defines extra functions for 'Data.Monoid.Endo' data type, and also@@ -46,11 +46,14 @@ license-file: LICENSE author: Peter Trško maintainer: peter.trsko@gmail.com-copyright: (c) 2013-2015, Peter Trško+copyright: (c) 2013-2016, Peter Trško category: Data build-type: Simple cabal-version: >=1.10 +-- See https://github.com/trskop/endo/blob/master/.travis.yml for more details.+tested-with: GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.1+ -- Examples require lens and optparse-applicative packages in addition to this -- packackage's dependencies. When using sandbox it is possible to use "cabal -- repl" to test examples by using following command:@@ -76,7 +79,10 @@ hs-source-dirs: src exposed-modules: Data.Monoid.Endo+ , Data.Monoid.Endo.AnEndo+ , Data.Monoid.Endo.Apply , Data.Monoid.Endo.Fold+ , Data.Monoid.Endo.FromEndo default-language: Haskell2010 other-extensions:@@ -88,18 +94,47 @@ build-depends: -- {{{ Distributed with GHC or Haskell Platform ---------------------------- base >=4.6 && <4.9- , transformers >=0.3 && <0.5+ base >=4.6 && <5+ , transformers >=0.3 && <0.6+ , mtl >=2.1 && <3+ -- ^ Version 2.1 is the first that supported transformers ==0.3, which is+ -- the lowest supported version by this package.+ -- }}} Distributed with GHC or Haskell Platform --------------------------- - , between >=0.9 && <0.11+ , between >=0.9 && <1+ , data-default-class ==0.0.* - if impl(GHC >= 7.8)- cpp-options: -DHAVE_MINIMAL_PRAGMA- -DKIND_POLYMORPHIC_TYPEABLE- if impl(GHC >= 7.9)- cpp-options: -DAPPLICATIVE_MONAD+ if impl(GHC >=7.8)+ cpp-options:+ -DHAVE_KIND_POLYMORPHIC_TYPEABLE+ -DHAVE_MINIMAL_PRAGMA + -- Module Data.Proxy, that defines Proxy data type, was+ -- introduced in base ==4.7.0.0, i.e. GHC 7.8.1.+ -DHAVE_PROXY++ if impl(GHC >=7.10)+ cpp-options:+ -- Applicative became supper class of Monad in base ==4.8 which was+ -- bundled with GHC 7.10.1 release.+ -DHAVE_APPLICATIVE_MONAD++ if impl(GHC >=8.0)+ cpp-options:+ -- Definition of Const moved in to its own module Data.Functor.Const in+ -- base 4.9.0.0, i.e. GHC 8.0.1.+ -DHAVE_FUNCTOR_CONST_MODULE++ -- Module Data.Functor.Classes has moved from transformers in to base+ -- 4.9.0.0, but the definitions in that module are compatible+ -- only with transformers >=0.5.+ -DHAVE_FUNCTOR_CLASSES++ -- Package base ==4.9.0.0 introduces Data.Semigroup, which was originally+ -- defined in semigroups package.+ -DHAVE_SEMIGROUPS+ ghc-options: -Wall if flag(pedantic) ghc-options:@@ -114,4 +149,4 @@ source-repository this type: git location: git://github.com/trskop/endo.git- tag: 0.2.0.1+ tag: 0.3.0.0
+ example/Example8.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleInstances #-}++module Main where++import Data.Functor.Identity++import Data.Monoid.Endo+import Data.Monoid.Endo.AnEndo++import Data.Default.Class (Default(def))+++data Verbosity+ = Silent+ | Normal+ | Verbose+ | Annoying+ deriving (Show {- ... -})++instance Default Verbosity where+ def = Normal++class HasVerbosity s where+ verbosity :: Functor f => (Verbosity -> f Verbosity) -> s -> f s++setVerbosity :: HasVerbosity s => Verbosity -> s -> s+setVerbosity v = runIdentity . verbosity (const (Identity v))++data Config = Config+ { cfgVerbosity :: Verbosity+ -- ...+ }+ deriving (Show)++instance HasVerbosity Config where+ verbosity f cfg@Config{cfgVerbosity = v} =+ (\v' -> cfg{cfgVerbosity = v'}) <$> f v++data Action = NormalAction Config | ShowVersion | ShowHelp+ deriving (Show {- ... -})++instance Default Config where+ def = Config+ { cfgVerbosity = def+ -- ...+ }++instance Default Action where+ def = NormalAction def++instance AnEndo Verbosity where+ type EndoOperatesOn Verbosity = Action++ anEndo v = Endo $ \case+ NormalAction cfg -> NormalAction $ setVerbosity v cfg+ action -> action
+ example/Example9.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleInstances #-}++module Main where++import Data.Functor.Identity++import Data.Text (Text)++import Data.Monoid.Endo+import Data.Monoid.Endo.AnEndo++import Data.Default.Class (Default(def))+++data User f g = User+ { _login :: Text+ , _name :: f Text+ , _displayName :: f Text+ , _password :: g Text+ }++type CreateUser = User Maybe Identity+type ShowUser = User Maybe Proxy+type AuthenticateUser = User Proxy Identity
+ src/Data/Monoid/Endo/AnEndo.hs view
@@ -0,0 +1,616 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}++#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+{-# LANGUAGE DeriveDataTypeable #-}+#endif++#if !MIN_VERSION_base(4,9,0) && MIN_VERSION_transformers(0,5,0)+-- Definitions in Data.Functor.Classes from transformers >=0.5 are compatible+-- with those in base >=4.9, therefore we can enable them.+#define HAVE_FUNCTOR_CLASSES+#endif++-- |+-- Module: $HEADER$+-- Description: Conversion of values in to endomorphisms.+-- Copyright: (c) 2014-2016, Peter Trško+-- License: BSD3+--+-- Maintainer: peter.trsko@gmail.com+-- Stability: experimental+-- Portability: CPP, DeriveDataTypeable, DeriveGeneric, FlexibleInstances,+-- NoImplicitPrelude, TypeFamilies+--+-- Conversion of values in to endomorphisms.+module Data.Monoid.Endo.AnEndo+ (+ -- * 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.+ AnEndo(..)++ -- ** WrappedFoldable+ --+ -- $wrappedFoldable+ , WrappedFoldable(..)++ -- * Utility Functions and Types+ , embedEndoWith+ , embedDualEndoWith+ )+ where++import Control.Applicative (Applicative)+import Control.Monad (Monad)+import Data.Foldable (Foldable(foldMap))+import Data.Function (($), (.), id)+import Data.Functor (Functor)+#ifdef HAVE_FUNCTOR_CLASSES+import Data.Functor.Classes+ ( Eq1+ , Ord1+ , Read1(liftReadsPrec)+ , Show1(liftShowsPrec)+ , readsData+ , readsUnaryWith+ , showsUnaryWith+ )+#endif+import Data.Functor.Identity (Identity(Identity))+import Data.Maybe (Maybe(Just, Nothing))+import Data.Monoid+ ( Dual(Dual, getDual)+ , Endo(Endo)+ , Monoid(mempty, mconcat)+ , (<>)+ )+#ifdef HAVE_SEMIGROUPS+import Data.Semigroup (Option(Option))+#endif+import Data.Traversable (Traversable)+import GHC.Generics (Generic, Generic1)+import Text.Read (Read)+import Text.Show (Show)++#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+import Data.Data (Data, Typeable)+#endif++#ifdef HAVE_PROXY+import Data.Proxy (Proxy(Proxy))+#endif++import Data.Functor.Reverse (Reverse)+++-- {{{ AnEndo Type Class ------------------------------------------------------++-- | 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.+class AnEndo a where+ -- | Extract type on which endomorphism operates, e.g. for+ -- @('Endo' a)@ it would be @a@.+ type EndoOperatesOn a++ -- | Convert value encoding @(a -> a)@ in to 'Endo'. Default+ -- implementation:+ --+ -- @+ -- 'anEndo' = 'getDual' . 'aDualEndo'+ -- @+ anEndo :: a -> Endo (EndoOperatesOn a)+ anEndo = getDual . aDualEndo++ -- | Dual to 'anEndo'. Default implementation:+ --+ -- @+ -- 'aDualEndo' = 'Dual' . 'anEndo'+ -- @+ aDualEndo :: a -> Dual (Endo (EndoOperatesOn a))+ aDualEndo = Dual . anEndo++#if HAVE_MINIMAL_PRAGMA+ {-# MINIMAL anEndo | aDualEndo #-}+#endif++instance AnEndo (Endo a) where+ type EndoOperatesOn (Endo a) = a+ anEndo = id++instance AnEndo (a -> a) where+ type EndoOperatesOn (a -> a) = a+ anEndo = Endo++instance AnEndo a => AnEndo (Identity a) where+ type EndoOperatesOn (Identity a) = EndoOperatesOn a++ anEndo (Identity e) = anEndo e+ aDualEndo (Identity e) = aDualEndo e++instance AnEndo a => AnEndo (Maybe a) where+ type EndoOperatesOn (Maybe a) = EndoOperatesOn a++ anEndo Nothing = mempty+ anEndo (Just e) = anEndo e++ aDualEndo Nothing = mempty+ aDualEndo (Just e) = aDualEndo e++#ifdef HAVE_PROXY+-- | Constructs identity endomorphism for specified phantom type.+instance AnEndo (Proxy a) where+ type EndoOperatesOn (Proxy a) = a++ anEndo Proxy = mempty+ aDualEndo Proxy = mempty+#endif++#ifdef HAVE_SEMIGROUPS+-- | Has same semantics as 'Maybe' and it is actually defined in terms of+-- 'AnEndo' instance for 'Maybe'.+instance AnEndo a => AnEndo (Option a) where+ type EndoOperatesOn (Option a) = EndoOperatesOn a++ anEndo (Option maybe) = anEndo maybe+ aDualEndo (Option maybe) = aDualEndo maybe+#endif++-- {{{ Foldable Instances -----------------------------------------------------++-- | Wrapper for 'Foldable' types. Used to provide instances that work for all+-- 'Foldable' types without the need for @OverlappingInstances@ language+-- extension.+newtype WrappedFoldable f a = WrapFoldable {getFoldable :: f a}+ deriving+ ( Applicative+ , Foldable+ , Functor+ , Generic+ , Generic1+ , Monad+ , Read+ , Show+ , Traversable+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Data+ , Typeable+#endif+#ifdef HAVE_FUNCTOR_CLASSES+ , Eq1+ , Ord1+#endif+ )++#ifdef HAVE_FUNCTOR_CLASSES+instance Read1 f => Read1 (WrappedFoldable f) where+ liftReadsPrec rp rl = readsData+ $ readsUnaryWith (liftReadsPrec rp rl) "WrapFoldable" WrapFoldable++instance Show1 f => Show1 (WrappedFoldable f) where+ liftShowsPrec sp sl d (WrapFoldable x) =+ showsUnaryWith (liftShowsPrec sp sl) "WrapFoldable" d x+#endif+ -- HAVE_FUNCTOR_CLASSES++instance (Foldable f, AnEndo a) => AnEndo (WrappedFoldable f a) where+ type EndoOperatesOn (WrappedFoldable f a) = EndoOperatesOn a+ anEndo (WrapFoldable fa) = foldMap anEndo fa+ aDualEndo (WrapFoldable fa) = foldMap aDualEndo fa++instance AnEndo a => AnEndo [a] where+ type EndoOperatesOn [a] = EndoOperatesOn a+ anEndo = anEndo . WrapFoldable+ aDualEndo = aDualEndo . WrapFoldable++-- {{{ Transformers -----------------------------------------------------------++-- | Fold in reverese order.+instance (Foldable f, AnEndo a) => AnEndo (Reverse f a) where+ type EndoOperatesOn (Reverse f a) = EndoOperatesOn a+ anEndo = anEndo . WrapFoldable+ aDualEndo = aDualEndo . WrapFoldable++-- }}} Transformers -----------------------------------------------------------++-- }}} Foldable Instances -----------------------------------------------------++-- {{{ Instances For Tuples ---------------------------------------------------++instance+ ( AnEndo a+ , AnEndo b+ , EndoOperatesOn a ~ EndoOperatesOn b+ ) => AnEndo (a, b)+ where+ type EndoOperatesOn (a, b) = EndoOperatesOn a+ anEndo (a, b) = anEndo a <> anEndo b+ aDualEndo (a, b) = aDualEndo a <> aDualEndo b++instance+ ( AnEndo a+ , AnEndo b+ , AnEndo c+ , EndoOperatesOn a ~ EndoOperatesOn b+ , EndoOperatesOn a ~ EndoOperatesOn c+ ) => AnEndo (a, b, c)+ where+ type EndoOperatesOn (a, b, c) = EndoOperatesOn a+ anEndo (a, b, c) = anEndo a <> anEndo b <> anEndo c+ aDualEndo (a, b, c) = aDualEndo a <> aDualEndo b <> aDualEndo c++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4) = EndoOperatesOn a1+ anEndo (a1, a2, a3, a4) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ ]++ aDualEndo (a1, a2, a3, a4) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ ]++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4, a5) = EndoOperatesOn a1++ anEndo (a1, a2, a3, a4, a5) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ , anEndo a5+ ]++ aDualEndo (a1, a2, a3, a4, a5) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ , aDualEndo a5+ ]++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4, a5, a6) = EndoOperatesOn a1++ anEndo (a1, a2, a3, a4, a5, a6) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ , anEndo a5+ , anEndo a6+ ]++ aDualEndo (a1, a2, a3, a4, a5, a6) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ , aDualEndo a5+ , aDualEndo a6+ ]++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7) = EndoOperatesOn a1++ anEndo (a1, a2, a3, a4, a5, a6, a7) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ , anEndo a5+ , anEndo a6+ , anEndo a7+ ]++ aDualEndo (a1, a2, a3, a4, a5, a6, a7) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ , aDualEndo a5+ , aDualEndo a6+ , aDualEndo a7+ ]++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8) = EndoOperatesOn a1++ anEndo (a1, a2, a3, a4, a5, a6, a7, a8) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ , anEndo a5+ , anEndo a6+ , anEndo a7+ , anEndo a8+ ]++ aDualEndo (a1, a2, a3, a4, a5, a6, a7, a8) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ , aDualEndo a5+ , aDualEndo a6+ , aDualEndo a7+ , aDualEndo a8+ ]++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9) = EndoOperatesOn a1++ anEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ , anEndo a5+ , anEndo a6+ , anEndo a7+ , anEndo a8+ , anEndo a9+ ]++ aDualEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ , aDualEndo a5+ , aDualEndo a6+ , aDualEndo a7+ , aDualEndo a8+ , aDualEndo a9+ ]++instance+ ( 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)+ where+ type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = EndoOperatesOn a1++ anEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = mconcat+ [ anEndo a1+ , anEndo a2+ , anEndo a3+ , anEndo a4+ , anEndo a5+ , anEndo a6+ , anEndo a7+ , anEndo a8+ , anEndo a9+ , anEndo a10+ ]++ aDualEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = mconcat+ [ aDualEndo a1+ , aDualEndo a2+ , aDualEndo a3+ , aDualEndo a4+ , aDualEndo a5+ , aDualEndo a6+ , aDualEndo a7+ , aDualEndo a8+ , aDualEndo a9+ , aDualEndo a10+ ]++-- }}} Instances For Tuples ---------------------------------------------------+-- }}} AnEndo Type Class ------------------------------------------------------++-- {{{ Utility Functions and Types --------------------------------------------++-- | Use 'Endo' (possibly result of 'Data.Endo.Fold.foldEndo') and use it to+-- create value of different type.+--+-- Examples:+--+-- @+-- 'embedEndoWith' 'Control.Monad.Trans.Writer.Lazy.tell'+-- :: (Monad m, 'AnEndo' e, w ~ 'EndoOperatesOn' e)+-- => e+-- -> 'Control.Monad.Trans.Writer.Lazy.WriterT' ('Endo' w) m ()+--+-- 'embedEndoWith' ('Control.Monad.Trans.State.Lazy.modify' . 'Data.Monoid.appEndo')+-- :: (Monad m, 'AnEndo' e, s ~ 'EndoOperatesOn' e)+-- => e+-- -> 'Control.Monad.Trans.State.Lazy.StateT' s m ()+-- @+--+-- See also 'embedDualEndoWith'.+embedEndoWith :: (AnEndo e, EndoOperatesOn e ~ a)+ => (Endo a -> b)+ -- ^ Embedding function.+ -> e -> b+embedEndoWith = (. anEndo)++-- | Dual to 'embedEndoWith', which uses 'aDualEndo' instead of 'anEndo'.+embedDualEndoWith+ :: (AnEndo e, EndoOperatesOn e ~ a)+ => (Dual (Endo a) -> b)+ -- ^ Embedding function.+ -> e -> b+embedDualEndoWith = (. aDualEndo)++-- }}} Utility Functions and Types --------------------------------------------++-- $wrappedFoldable+--+-- Newtype 'WrappedFoldable' allows us to use 'anEndo', 'aDualEndo',+-- 'Data.Endo.Fold.foldEndo', and 'Data.Endo.Fold.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 ('Data.Monoid.Endo.E' a) -> 'Endo' a+-- @+--+-- @+-- \\vectorOfEndos -> 'Data.Monoid.Endo.Fold.foldEndo' ('WrappedFoldable' vectorOfEndos)+-- :: 'Data.Monoid.Endo.Fold.FoldEndoArgs' => Vector ('Data.Monoid.Endo.E' a) -> args+-- @+--+-- Note that the @Vector@ is just one of possible 'Foldable' data types that+-- may be used here. Also, @('Data.Monoid.Endo.E' a)@ is just an example of+-- endomorphism representation, any 'AnEndo' instance can be used.
+ src/Data/Monoid/Endo/Apply.hs view
@@ -0,0 +1,425 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-} -- GeneralizedNewtypeDeriving failed.+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}++#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+{-# LANGUAGE DeriveDataTypeable #-}+#endif++#if MIN_VERSION_transformers(0,5,0) || MIN_VERSION_base(4,9,0)+#define HAVE_FUNCTOR_CLASSES+#endif++-- |+-- Module: $HEADER$+-- Description: ApplyEndo provides easier endomorphism evaluation in cases+-- when there is an "obvious" default value.+-- Copyright: (c) 2015-2016, Peter Trško+-- License: BSD3+--+-- Maintainer: peter.trsko@gmail.com+-- Stability: experimental+-- Portability: CPP, DeriveFoldable, DeriveFunctor, DeriveDataTypeable,+-- DeriveGeneric, DeriveTraversable, FlexibleInstances,+-- NoImplicitPrelude, TypeFamilies+--+-- 'ApplyEndo' provides easier endomorphism evaluation in cases when there is an+-- \"obvious\" default value.+module Data.Monoid.Endo.Apply+ (+ -- * ApplyEndo+ ApplyEndo(..)+ , apply+ , applyF++ -- ** ApplyEndo Mempty+ , Mempty+ , applyMempty+ , applyMempty_+ , joinApplyMempty++ -- ** ApplyEndo Def+ --+ -- $applyEndoDef+ , Def+ , applyDef+ , applyDef_+ , joinApplyDef++ -- ** ApplyEndo Reader+ , Reader+ , applyReader+ , applyReaderWith+ , joinApplyReader++ -- ** ApplyEndo Modify+ , Modify+ , applyModify+ , joinApplyModify++ -- ** ApplyEndo Modify'+ , Modify'+ , applyModify'+ , joinApplyModify'++ )+ where++import Prelude (seq)++import Control.Applicative (Applicative(pure))+import Control.Monad+ ( Monad((>>=))+#ifdef HAVE_APPLICATIVE_MONAD+ , void+#else+ , liftM+#endif+ )+import Data.Foldable (Foldable)+import Data.Function+ ( (.)+ , ($)+#ifndef HAVE_APPLICATIVE_MONAD+ , const+#endif+ )+import Data.Functor (Functor, (<$>))+#ifdef HAVE_FUNCTOR_CLASSES+import Data.Functor.Classes+ ( Eq1+ , Ord1+ , Read1(liftReadsPrec)+ , Show1(liftShowsPrec)+ , readsData+ , readsUnaryWith+ , showsUnaryWith+ )+#endif+import Data.Functor.Identity (Identity(runIdentity))+import Data.Monoid (Endo(Endo, appEndo), Monoid(mempty))+import Data.Traversable (Traversable)+import GHC.Generics (Generic, Generic1)++#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+import Data.Data (Data, Typeable)+#endif++import Control.Monad.Reader.Class (MonadReader)+import qualified Control.Monad.Reader.Class as MonadReader (asks)+import Control.Monad.State.Class (MonadState)+import qualified Control.Monad.State.Class as MonadState (state)++import Data.Default.Class (Default(def))++import Data.Monoid.Endo.FromEndo (FromEndo(..))+++-- | There are cases when it is \"obvious\" what is the default value, which+-- should be modified by the endomorphism. This type is a result of such+-- endomorphism application and it uses phantom type @t@ as distinguishing+-- property, which decides what is the correct \"default value\".+newtype ApplyEndo t f a = ApplyEndo {applyEndo :: f a}+ deriving+ ( Applicative+ , Foldable+ , Functor+ , Generic+ , Generic1+ , Monad+ , Traversable+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Data+ , Typeable+#endif+#ifdef HAVE_FUNCTOR_CLASSES+ , Eq1+ , Ord1+#endif+ )++#ifdef HAVE_FUNCTOR_CLASSES+instance Read1 f => Read1 (ApplyEndo t f) where+ liftReadsPrec rp rl =+ readsData $ readsUnaryWith (liftReadsPrec rp rl) "ApplyEndo" ApplyEndo++instance Show1 f => Show1 (ApplyEndo t f) where+ liftShowsPrec sp sl d (ApplyEndo x) =+ showsUnaryWith (liftShowsPrec sp sl) "ApplyEndo" d x+#endif+ -- HAVE_FUNCTOR_CLASSES++-- | Apply endomorphism using provided \"default\" value.+apply :: Applicative f => a -> Endo a -> ApplyEndo t f a+apply defaultValue (Endo f) = ApplyEndo . pure $ f defaultValue+{-# INLINE apply #-}++-- | Similar as 'apply', but expects 'Endo' to be wrapped by a 'Functor'.+applyF :: Functor f => a -> f (Endo a) -> ApplyEndo t f a+applyF defaultValue endo = ApplyEndo $ (`appEndo` defaultValue) <$> endo++-- {{{ ApplyEndo Mempty -------------------------------------------------------++-- | Type tag identifying usage of 'mempty' from 'Monoid'.+data Mempty+ deriving+ ( Generic+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Typeable+#endif+ )++instance (Applicative f, Monoid a) => FromEndo (ApplyEndo Mempty f a) where+ type EndoOperatedOn (ApplyEndo Mempty f a) = a++ fromEndo = apply mempty++-- | Constrained version of 'applyEndo'. Usage example:+--+-- @+-- applyMempty . fromEndo :: ('Applicative' f, 'Monoid' a) => 'Endo' a -> f a+-- @+applyMempty :: Monoid a => ApplyEndo Mempty f a -> f a+applyMempty = applyEndo+{-# INLINE applyMempty #-}++-- | Same as 'applyMempty', but 'Applicative' functor is specialized to+-- 'Identity' functor and evaluated.+--+-- Examples:+--+-- >>> fromEndoWith applyMempty_ $ foldEndo (+1) [(*10), (+42)] :: Int+-- 421+-- >>> fromEndoWith applyMempty_ $ dualFoldEndo (+1) [(*10), (+42)] :: Int+-- 52+applyMempty_ :: Monoid a => ApplyEndo Mempty Identity a -> a+applyMempty_ = runIdentity . applyMempty+{-# INLINE applyMempty_ #-}++-- | Evaluates 'ApplyEndo' in a 'Monad' by joining it with the monad it+-- contains. It can be also viewed as a variant of 'applyMempty' defined as:+--+-- @+-- 'joinApplyMempty' = ('>>=' 'applyMempty')+-- @+joinApplyMempty+ :: ( Monad m+ , Monoid a+#ifndef HAVE_APPLICATIVE_MONAD+ , Applicative m+#endif+ )+ => m (ApplyEndo Mempty m a) -> m a+joinApplyMempty = (>>= applyMempty)+{-# INLINE joinApplyMempty #-}++-- }}} ApplyEndo Mempty -------------------------------------------------------++-- {{{ ApplyEndo Def ----------------------------------------------------------++-- $applyEndoDef+--+-- Apply endomorphism to a default value 'def' from 'Default'. See also+-- following packages:+--+-- * <https://hackage.haskell.org/package/data-default-extra data-default-extra>+--+-- * <https://hackage.haskell.org/package/data-default data-default>+--+-- Both of those packages provide additional instances to 'Default' type+-- class.++-- | Type tag identifying usage of 'def' from 'Default'.+data Def+ deriving+ ( Generic+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Typeable+#endif+ )++instance (Applicative f, Default a) => FromEndo (ApplyEndo Def f a) where+ type EndoOperatedOn (ApplyEndo Def f a) = a++ fromEndo = apply def++-- | Constrained version of 'applyEndo'. Usage example:+--+-- @+-- applyDef . fromEndo :: ('Applicative' f, 'Default' a) => 'Endo' a -> f a+-- @+applyDef :: (Applicative f, Default a) => ApplyEndo Def f a -> f a+applyDef = applyEndo+{-# INLINE applyDef #-}++-- | Same as 'applyDef', but 'Applicative' functor is specialized to 'Identity'+-- functor and evaluated.+--+-- Examples:+--+-- >>> fromEndoWith applyDef_ $ foldEndo (+1) [(*10), (+42)] :: Int+-- 421+-- >>> fromEndoWith applyDef_ $ dualFoldEndo (+1) [(*10), (+42)] :: Int+-- 52+applyDef_ :: Default a => ApplyEndo Def Identity a -> a+applyDef_ = runIdentity . applyDef+{-# INLINE applyDef_ #-}++-- | Evaluates 'ApplyEndo' in a 'Monad' by joining it with the monad it+-- contains. It can be also viewed as a variant of 'applyDef' defined as:+--+-- @+-- 'joinApplyDef' = ('>>=' 'applyDef')+-- @+joinApplyDef+ :: ( Monad m+ , Default a+#ifndef HAVE_APPLICATIVE_MONAD+ , Applicative m+#endif+ )+ => m (ApplyEndo Def m a) -> m a+joinApplyDef = (>>= applyDef)+{-# INLINE joinApplyDef #-}++-- }}} ApplyEndo Def ----------------------------------------------------------++-- {{{ ApplyEndo Reader -------------------------------------------------------++-- | Type tag identifying usage of 'MonadReader.asks' operation in 'FromEndo'+-- instance of 'ApplyEndo'.+data Reader+ deriving+ ( Generic+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Typeable+#endif+ )++-- | Evaluates 'ApplyEndo' in terms of 'MonadReader.asks' operation:+--+-- @+-- 'fromEndo' = 'ApplyEndo' . 'MonadReader.asks' . 'appEndo'+-- @+instance MonadReader r m => FromEndo (ApplyEndo Reader m r) where+ type EndoOperatedOn (ApplyEndo Reader m r) = r++ fromEndo = ApplyEndo . MonadReader.asks . appEndo++-- | Evaluates 'ApplyEndo' in terms of 'MonadReader.asks' operation.+--+-- This @(->) r@ is a valid 'MonadReader' instance, therefore, this is a valid+-- use case:+--+-- >>> (applyReader . fromEndo $ foldEndo (*10) (+1)) 0 :: Int+-- 10+applyReader :: MonadReader r m => ApplyEndo Reader m r -> m r+applyReader = applyEndo++-- | Evaluates 'ApplyEndo' in terms of 'MonadReader.asks' operation and then+-- evaluates the resalt using provided function.+--+-- This @(->) r@ is a valid 'MonadReader' instance, therefore, this is a valid+-- use case:+--+-- >>> applyReaderWith ($ 0) . fromEndo $ foldEndo (*10) (+1) :: Int+-- 10+applyReaderWith :: MonadReader r m => (m r -> a) -> ApplyEndo Reader m r -> a+applyReaderWith = (. applyEndo)++-- | Evaluates 'ApplyEndo' in a 'Monad' by joining it with the monad it+-- contains. It can be also viewed as a variant of 'applyReader' defined as:+--+-- @+-- 'joinApplyReader' = ('>>=' 'applyReader')+-- @+joinApplyReader :: MonadReader r m => m (ApplyEndo Reader m r) -> m r+joinApplyReader = (>>= applyEndo)++-- }}} ApplyEndo Reader -------------------------------------------------------++-- {{{ ApplyEndo Modify -------------------------------------------------------++-- | Type tag identifying usage of 'MonadState.state' operation in 'FromEndo'+-- instance of 'ApplyEndo'.+data Modify+ deriving+ ( Generic+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Typeable+#endif+ )++-- | Evaluates 'ApplyEndo' in terms of 'MonadState.state' operation:+--+-- @+-- 'fromEndo' e = 'ApplyEndo' . 'MonadState.state' '$' \\s ->+-- let s' = 'appEndo' e s in (s', s')+-- @+instance MonadState s m => FromEndo (ApplyEndo Modify m s) where+ type EndoOperatedOn (ApplyEndo Modify m s) = s++ fromEndo e =+ ApplyEndo . MonadState.state $ \s -> let s' = appEndo e s in (s', s')++-- | Evaluates 'ApplyEndo' in terms of 'MonadState.state' operation.+applyModify :: MonadState s m => ApplyEndo Modify m s -> m s+applyModify = applyEndo++-- | Evaluates 'ApplyEndo' in a 'Monad' by joining it with the monad it+-- contains. It can be also viewed as a variant of 'applyModify' defined as:+--+-- @+-- 'joinApplyModify' = ('>>=' 'applyModify')+-- @+joinApplyModify :: MonadState s m => m (ApplyEndo Modify m s) -> m s+joinApplyModify = (>>= applyEndo)++-- | Same as 'Modify', but strictness is implied.+data Modify'+ deriving+ ( Generic+#ifdef HAVE_KIND_POLYMORPHIC_TYPEABLE+ , Typeable+#endif+ )++-- | Evaluates 'ApplyEndo' in terms of 'MonadState.state' operation:+--+-- @+-- 'fromEndo' ('Endo' f) = 'ApplyEndo' . 'MonadState.state' $ \\s ->+-- let s' = f s in s' \`seq\` (s', s')+-- @+instance MonadState s m => FromEndo (ApplyEndo Modify' m s) where+ type EndoOperatedOn (ApplyEndo Modify' m s) = s++ fromEndo (Endo f) =+ ApplyEndo . MonadState.state $ \s -> let s' = f s in s' `seq` (s', s')++-- | Evaluates 'ApplyEndo' in terms of 'MonadState.state' operation.+applyModify' :: MonadState r m => ApplyEndo Modify' m () -> m ()+applyModify' = void . applyEndo++-- | Evaluates 'ApplyEndo' in a 'Monad' by joining it with the monad it+-- contains. It can be also viewed as a variant of 'applyModify'' defined as:+--+-- @+-- 'joinApplyModify'' = ('>>=' 'applyModify'')+-- @+joinApplyModify' :: MonadState r m => m (ApplyEndo Modify' m r) -> m r+joinApplyModify' = (>>= applyEndo)++-- }}} ApplyEndo Modify -------------------------------------------------------++-- {{{ Helper functions (not exported) ----------------------------------------++#ifndef HAVE_APPLICATIVE_MONAD+void :: Monad m => m a -> m ()+void = liftM $ const ()+#endif++-- {{{ Helper functions (not exported) ----------------------------------------
src/Data/Monoid/Endo/Fold.hs view
@@ -1,12 +1,9 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-}--#ifdef KIND_POLYMORPHIC_TYPEABLE-{-# LANGUAGE DeriveDataTypeable #-}-#endif+{-# LANGUAGE TypeOperators #-} #if MIN_VERSION_transformers(0,4,0) -- ExceptT was introduced in transformers == 0.4.0.0 and it deprecated ErrorT.@@ -14,22 +11,16 @@ #define HAVE_EXCEPTT #endif -#if MIN_VERSION_base(4,7,0)--- Module Data.Proxy, that defines Proxy data type, was introduced in--- base == 4.7.0.0.-#define HAVE_PROXY-#endif- -- | -- Module: $HEADER$ -- Description: Generic folding for various endomorphism representations.--- Copyright: (c) 2014-2015, Peter Trško+-- Copyright: (c) 2014-2016, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com -- Stability: experimental -- Portability: CPP, DeriveDataTypeable, DeriveGeneric, FlexibleInstances,--- NoImplicitPrelude, TypeFamilies+-- NoImplicitPrelude, RankNTypes, TypeOperators, TypeFamilies -- -- Generic folding for various endomorphism representations. module Data.Monoid.Endo.Fold@@ -65,7 +56,8 @@ -- ** Type Wrappers , WrappedFoldable(..) - -- * Utility Functions+ -- * Utility Functions and Types+ , (:->) , (&$) , (<&$>) , embedEndoWith@@ -73,29 +65,24 @@ ) where -import Control.Applicative (Applicative(pure), Const(Const))+import Control.Applicative+ ( Applicative(pure)+#ifndef HAVE_FUNCTOR_CONST_MODULE+ , Const(Const)+#endif+ ) import Control.Monad (Monad(return)) import Data.Either (Either(Right))-import Data.Foldable (Foldable(foldMap)) import Data.Function ((.), id) import Data.Functor (Functor(fmap))+#ifdef HAVE_FUNCTOR_CONST_MODULE+import Data.Functor.Const (Const(Const))+#endif import Data.Functor.Identity (Identity(Identity))-import Data.Maybe (Maybe(Just, Nothing))-import Data.Monoid (Dual(Dual, getDual), Endo(Endo), Monoid(mempty, mconcat), (<>))-import GHC.Generics (Generic)+import Data.Maybe (Maybe(Just))+import Data.Monoid (Dual(Dual), Endo, Monoid(mempty), (<>)) import System.IO (IO)-import Text.Read (Read)-import Text.Show (Show) -#ifdef KIND_POLYMORPHIC_TYPEABLE-import Data.Data (Data)-import Data.Typeable (Typeable)-#endif--#ifdef HAVE_PROXY-import Data.Proxy (Proxy(Proxy))-#endif- #ifdef HAVE_EXCEPTT import Control.Monad.Trans.Except (ExceptT) #endif@@ -111,9 +98,15 @@ import qualified Control.Monad.Trans.Writer.Strict as Strict (WriterT) import Data.Functor.Compose (Compose) import Data.Functor.Product (Product)-import Data.Functor.Reverse (Reverse) +import Data.Monoid.Endo.AnEndo+ ( AnEndo(..)+ , WrappedFoldable(..)+ , embedDualEndoWith+ , embedEndoWith+ ) + -- | Fold all variously represented endomorphisms in to one endomorphism. -- -- Order in which endomorphisms are folded is preserved:@@ -141,7 +134,7 @@ -- Order in which endomorphisms are folded is reversed: -- -- >>> dualFoldEndo (Endo (1:)) [(2:), (3:)] `appEndo` []--- [2,3,1]+-- [3,2,1] -- -- For numbers it would look like: --@@ -230,8 +223,8 @@ -- Examples: -- -- @--- 'foldEndo' \<*\> ((++) \<$\> getLine) \<*\> ((++) \<$\> getLine)--- :: :: ('FoldEndoArgs' r, 'ResultOperatesOn' r ~ String) => IO r+-- 'foldEndo' \<*\> ((<>) \<$\> getLine) \<*\> ((<>) \<$\> getLine)+-- :: ('FoldEndoArgs' r, 'ResultOperatesOn' r ~ String) => IO r -- @ -- -- In the next example, prefix @ghci\>@ indicates GHCi prompt, @ghci|@ is GHCi@@ -304,7 +297,7 @@ #ifdef HAVE_EXCEPTT instance ( Monad m-#ifndef APPLICATIVE_MONAD+#ifndef HAVE_APPLICATIVE_MONAD , Functor m #endif , FoldEndoArgs r@@ -324,7 +317,7 @@ instance ( Monad m-#ifndef APPLICATIVE_MONAD+#ifndef HAVE_APPLICATIVE_MONAD , Functor m #endif , FoldEndoArgs r@@ -342,7 +335,7 @@ instance ( Monad m-#ifndef APPLICATIVE_MONAD+#ifndef HAVE_APPLICATIVE_MONAD , Functor m #endif , Monoid w@@ -356,7 +349,7 @@ instance ( Monad m-#ifndef APPLICATIVE_MONAD+#ifndef HAVE_APPLICATIVE_MONAD , Functor m #endif , Monoid w@@ -401,422 +394,29 @@ -- }}} Transformers ----------------------------------------------------------- --- {{{ FoldEndoArgs Type Class ------------------------------------------------+-- }}} FoldEndoArgs Type Class ------------------------------------------------ --- {{{ AnEndo Type Class ------------------------------------------------------+-- {{{ Utility Functions and Types -------------------------------------------- --- | 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.+-- | Type alias that restricts type of endomorphism folding result, and it+-- looks similar to @->@. Example of creating version of 'foldEndo' with+-- specific result: -- -- @--- instance 'AnEndo' ('Proxy' a) where--- type 'EndoOperatesOn' ('Proxy' a) = a------ 'anEndo' _ = 'mempty' -- = Endo 'id'--- 'aDualEndo' _ = 'mempty'+-- foldToEndoString :: 'FoldEndoArgs' args => args ':->' 'Endo' String+-- foldToEndoString = 'foldEndo' -- @ ----- 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+-- >>> foldToEndoString ("foo" <>) ("bar" <>) `appEndo` "baz"+-- "foobarbaz" ----- 'anEndo' Nothing = 'mempty' -- = Endo 'id'--- 'anEndo' (Just e) = 'anEndo' e+-- Following type signatures for 'foldEndoArgs' are equivalent: ----- -- Definition of 'aDualEndo' is analogous. -- @------ Instance for @Maybe@ lets us conditionally inject endomorphism in to a--- folding chain.-class AnEndo a where- -- | Extract type on which endomorphism operates, e.g. for- -- @'Endo' a@ it would be @a@.- type EndoOperatesOn a-- -- | Convert value encoding @a -> a@ in to 'Endo'. Default implementation:- --- -- @- -- 'anEndo' = 'getDual' . 'aDualEndo'- -- @- anEndo :: a -> Endo (EndoOperatesOn a)- anEndo = getDual . aDualEndo-- -- | Dual to 'anEndo'. Default implementation:- --- -- @- -- 'aDualEndo' = 'Dual' . 'anEndo'- -- @- aDualEndo :: a -> Dual (Endo (EndoOperatesOn a))- aDualEndo = Dual . anEndo--#if HAVE_MINIMAL_PRAGMA- {-# MINIMAL anEndo | aDualEndo #-}-#endif--instance AnEndo (Endo a) where- type EndoOperatesOn (Endo a) = a- anEndo = id--instance AnEndo (a -> a) where- type EndoOperatesOn (a -> a) = a- anEndo = Endo--instance AnEndo a => AnEndo (Maybe a) where- type EndoOperatesOn (Maybe a) = EndoOperatesOn a-- anEndo Nothing = mempty- anEndo (Just e) = anEndo e-- aDualEndo Nothing = mempty- aDualEndo (Just e) = aDualEndo e--#ifdef HAVE_PROXY--- | Constructs identity endomorphism for specified phantom type.-instance AnEndo (Proxy a) where- type EndoOperatesOn (Proxy a) = a-- anEndo Proxy = mempty- aDualEndo Proxy = mempty-#endif---- {{{ Foldable Instances --------------------------------------------------------- | Wrapper for 'Foldable' instances.------ This allows using 'foldEndo' and 'dualFoldEndo' for any 'Foldable' instance--- without the need for @OverlappingInstances@ language extension.-newtype WrappedFoldable f a = WrapFoldable {getFoldable :: f a}- deriving- ( Generic- , Read- , Show-#ifdef KIND_POLYMORPHIC_TYPEABLE- , Data- , Typeable-#endif- )--instance (Foldable f, AnEndo a) => AnEndo (WrappedFoldable f a) where- type EndoOperatesOn (WrappedFoldable f a) = EndoOperatesOn a- anEndo (WrapFoldable fa) = foldMap anEndo fa- aDualEndo (WrapFoldable fa) = foldMap aDualEndo fa--instance AnEndo a => AnEndo [a] where- type EndoOperatesOn [a] = EndoOperatesOn a- anEndo = anEndo . WrapFoldable- aDualEndo = aDualEndo . WrapFoldable---- {{{ Transformers --------------------------------------------------------------- | Fold in reverese order.-instance (Foldable f, AnEndo a) => AnEndo (Reverse f a) where- type EndoOperatesOn (Reverse f a) = EndoOperatesOn a- anEndo = anEndo . WrapFoldable- aDualEndo = aDualEndo . WrapFoldable---- }}} Transformers --------------------------------------------------------------- }}} Foldable Instances --------------------------------------------------------- {{{ Instances For Tuples -----------------------------------------------------instance- ( AnEndo a- , AnEndo b- , EndoOperatesOn a ~ EndoOperatesOn b- ) => AnEndo (a, b)- where- type EndoOperatesOn (a, b) = EndoOperatesOn a- anEndo (a, b) = anEndo a <> anEndo b- aDualEndo (a, b) = aDualEndo a <> aDualEndo b--instance- ( AnEndo a- , AnEndo b- , AnEndo c- , EndoOperatesOn a ~ EndoOperatesOn b- , EndoOperatesOn a ~ EndoOperatesOn c- ) => AnEndo (a, b, c)- where- type EndoOperatesOn (a, b, c) = EndoOperatesOn a- anEndo (a, b, c) = anEndo a <> anEndo b <> anEndo c- aDualEndo (a, b, c) = aDualEndo a <> aDualEndo b <> aDualEndo c--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4) = EndoOperatesOn a1- anEndo (a1, a2, a3, a4) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- ]-- aDualEndo (a1, a2, a3, a4) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- ]--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4, a5) = EndoOperatesOn a1-- anEndo (a1, a2, a3, a4, a5) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- , anEndo a5- ]-- aDualEndo (a1, a2, a3, a4, a5) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- , aDualEndo a5- ]--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4, a5, a6) = EndoOperatesOn a1-- anEndo (a1, a2, a3, a4, a5, a6) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- , anEndo a5- , anEndo a6- ]-- aDualEndo (a1, a2, a3, a4, a5, a6) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- , aDualEndo a5- , aDualEndo a6- ]--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7) = EndoOperatesOn a1-- anEndo (a1, a2, a3, a4, a5, a6, a7) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- , anEndo a5- , anEndo a6- , anEndo a7- ]-- aDualEndo (a1, a2, a3, a4, a5, a6, a7) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- , aDualEndo a5- , aDualEndo a6- , aDualEndo a7- ]--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8) = EndoOperatesOn a1-- anEndo (a1, a2, a3, a4, a5, a6, a7, a8) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- , anEndo a5- , anEndo a6- , anEndo a7- , anEndo a8- ]-- aDualEndo (a1, a2, a3, a4, a5, a6, a7, a8) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- , aDualEndo a5- , aDualEndo a6- , aDualEndo a7- , aDualEndo a8- ]--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9) = EndoOperatesOn a1-- anEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- , anEndo a5- , anEndo a6- , anEndo a7- , anEndo a8- , anEndo a9- ]-- aDualEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- , aDualEndo a5- , aDualEndo a6- , aDualEndo a7- , aDualEndo a8- , aDualEndo a9- ]--instance- ( 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)- where- type EndoOperatesOn (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = EndoOperatesOn a1-- anEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = mconcat- [ anEndo a1- , anEndo a2- , anEndo a3- , anEndo a4- , anEndo a5- , anEndo a6- , anEndo a7- , anEndo a8- , anEndo a9- , anEndo a10- ]-- aDualEndo (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = mconcat- [ aDualEndo a1- , aDualEndo a2- , aDualEndo a3- , aDualEndo a4- , aDualEndo a5- , aDualEndo a6- , aDualEndo a7- , aDualEndo a8- , aDualEndo a9- , aDualEndo a10- ]---- }}} Instances For Tuples ------------------------------------------------------ }}} AnEndo Type Class ---------------------------------------------------------- {{{ Utility Functions ------------------------------------------------------+-- 'FoldEndoArgs' args => args ':->' 'Endo' String+-- ('FoldEndoArgs' args, 'Result' args ~ 'Endo' String) => args+-- @+type args :-> r = (Result args ~ r) => args -- | Variant of function @('Data.Function.$') :: (a -> b) -> a -> b@, from -- "Data.Function" module, but with fixity as@@ -833,39 +433,7 @@ (<&$>) = fmap infixl 1 <&$> --- | Use 'Endo' (possibly result of 'foldEndo') and use it to create value of--- different type.------ Examples:------ @--- 'embedEndoWith' 'Control.Monad.Trans.Writer.Lazy.tell'--- :: (Monad m, 'AnEndo' e, w ~ 'EndoOperatesOn' e)--- => e--- -> 'Control.Monad.Trans.Writer.Lazy.WriterT' ('Endo' w) m ()------ 'embedEndoWith' 'Control.Monad.Trans.State.Lazy.modify'--- :: (Monad m, 'AnEndo' e, s ~ 'EndoOperatesOn' e)--- => e--- -> 'Control.Monad.Trans.State.Lazy.StateT' s m ()--- @------ See also 'embedDualEndoWith'.-embedEndoWith :: (AnEndo e, EndoOperatesOn e ~ a)- => (Endo a -> b)- -- ^ Embedding function.- -> e -> b-embedEndoWith = (. anEndo)---- | Dual to 'embedEndoWith', which uses 'aDualEndo' instead of 'anEndo'.-embedDualEndoWith- :: (AnEndo e, EndoOperatesOn e ~ a)- => (Dual (Endo a) -> b)- -- ^ Embedding function.- -> e -> b-embedDualEndoWith = (. aDualEndo)---- }}} Utility Functions ------------------------------------------------------+-- }}} Utility Functions and Types -------------------------------------------- -- $basicIdea --@@ -873,7 +441,7 @@ -- -- @ -- data Verbosity = Silent | Normal | Verbose | Annoying--- deriving (Bounded, Data, Enum, Eq, Ord, Show, Typeable)+-- deriving (Show) -- -- data Config = Config -- { _verbosity :: Verbosity
+ src/Data/Monoid/Endo/FromEndo.hs view
@@ -0,0 +1,194 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE TypeFamilies #-}+-- |+-- Module: $HEADER$+-- Description: Convert endomorphism in to a value.+-- Copyright: (c) 2015, Peter Trško+-- License: BSD3+--+-- Maintainer: peter.trsko@gmail.com+-- Stability: experimental+-- Portability: NoImplicitPrelude+--+-- Convert endomorphism in to a value.+module Data.Monoid.Endo.FromEndo+ (+ -- * Convert Endo to a Value+ FromEndo(..)+ , fromEndoWith+ , fromEndoWithF+ , fromDualEndoWith+ , fromDualEndoWithF+ , fromEndoTo+ , fromDualEndoTo+ )+ where++import Control.Monad (Monad)+import Data.Function ((.), id)+import Data.Functor (Functor(fmap))+import Data.Monoid (Dual(Dual, getDual), Endo(Endo, appEndo), Monoid)++import Control.Monad.Trans.Reader (ReaderT)+import Control.Monad.Trans.Reader as Reader (asks)+import Control.Monad.Trans.RWS.Lazy as Lazy (RWST)+import Control.Monad.Trans.RWS.Lazy as Lazy.RWS (modify)+import Control.Monad.Trans.RWS.Strict as Strict (RWST)+import Control.Monad.Trans.RWS.Strict as Strict.RWS (modify)+import Control.Monad.Trans.State.Lazy as Lazy (StateT)+import Control.Monad.Trans.State.Lazy as Lazy.State (modify)+import Control.Monad.Trans.State.Strict as Strict (StateT)+import Control.Monad.Trans.State.Strict as Strict.State (modify)+++-- | Type class provides functionality for converting @'Endo' b@ and @'Dual'+-- ('Endo' b)@ in to some type @a@. Type @b@, on which endomorphism operates,+-- is implied by type @a@, but generally aren't the same type. In other words+-- it is dual type class to 'Data.Monoid.Endo.AnEndo'.+class FromEndo a where+ type EndoOperatedOn a++ -- | Convert endomorphism in to a value of type @a@.+ fromEndo :: Endo (EndoOperatedOn a) -> a++ -- | Provided default implementation:+ --+ -- @+ -- 'fromDualEndo' = 'fromEndo' '.' 'getDual'+ -- @+ fromDualEndo :: Dual (Endo (EndoOperatedOn a)) -> a+ fromDualEndo = fromEndo . getDual++#ifdef HAVE_MINIMAL_PRAGMA+ {-# MINIMAL fromEndo #-}+#endif++instance FromEndo (a -> a) where+ type EndoOperatedOn (a -> a) = a++ fromEndo = appEndo+ fromDualEndo = appEndo . getDual++instance FromEndo (Endo a) where+ type EndoOperatedOn (Endo a) = a++ fromEndo = id+ fromDualEndo = getDual++instance FromEndo e => FromEndo (Dual e) where+ type EndoOperatedOn (Dual e) = EndoOperatedOn e++ fromEndo = Dual . fromEndo+ fromDualEndo = Dual . fromDualEndo++-- {{{ Transformers instances for FromEndo ------------------------------------++-- | Retrieve environment modified by endomorphism.+--+-- @+-- 'fromEndo' ('Endo' f) = 'Reader.asks' f+-- @+instance Monad f => FromEndo (ReaderT r f r) where+ type EndoOperatedOn (ReaderT r f r) = r++ fromEndo (Endo f) = Reader.asks f++-- | Modify state.+--+-- @+-- 'fromEndo' ('Endo' f) = 'Lazy.RWS.modify' f+-- @+instance (Monoid w, Monad f) => FromEndo (Lazy.RWST r w s f ()) where+ type EndoOperatedOn (Lazy.RWST r w s f ()) = s++ fromEndo (Endo f) = Lazy.RWS.modify f++-- | Modify state.+--+-- @+-- 'fromEndo' ('Endo' f) = 'Strict.RWS.modify' f+-- @+instance (Monoid w, Monad f) => FromEndo (Strict.RWST r w s f ()) where+ type EndoOperatedOn (Strict.RWST r w s f ()) = s++ fromEndo (Endo f) = Strict.RWS.modify f++-- | Modify state.+--+-- @+-- 'fromEndo' ('Endo' f) = 'Lazy.State.modify' f+-- @+instance Monad f => FromEndo (Lazy.StateT s f ()) where+ type EndoOperatedOn (Lazy.StateT s f ()) = s++ fromEndo (Endo f) = Lazy.State.modify f++-- | Modify state.+--+-- @+-- 'fromEndo' ('Endo' f) = 'Strict.State.modify' f+-- @+instance Monad f => FromEndo (Strict.StateT s f ()) where+ type EndoOperatedOn (Strict.StateT s f ()) = s++ fromEndo (Endo f) = Strict.State.modify f++-- }}} Transformers instances for FromEndo ------------------------------------++-- | In a lot of cases it is necessary to evaluate result of 'fromEndo'.+-- Example:+--+-- >>> fromEndoWith ((`runState` def) :: State Int () -> ((), Int)) (Endo (+10))+-- ((), 10)+--+-- Following property holds:+--+-- @+-- 'fromEndoWith' 'id' = 'fromEndo'+-- @+--+-- See also 'fromDualEndoWith'.+fromEndoWith :: (FromEndo a, EndoOperatedOn a ~ c) => (a -> b) -> Endo c -> b+fromEndoWith = (. fromEndo)++-- | Same as 'fromEndoWith', but deals with 'Endo' wrapped inside a 'Functor'.+fromEndoWithF+ :: (Functor f, FromEndo a, EndoOperatedOn a ~ c)+ => (f a -> b) -> f (Endo c) -> b+fromEndoWithF = (. fmap fromEndo)++-- | In a lot of cases it is necessary to evaluate result of 'fromDualEndo'.+-- Example:+--+-- >>> fromEndoWith ((`runState` def) :: State Int () -> ((), Int)) (Dual (Endo (+10)))+-- ((), 10)+--+-- Following property holds:+--+-- @+-- 'fromDualEndoWith' 'id' = 'fromDualEndo'+-- @+--+-- See also 'fromEndoWith'.+fromDualEndoWith+ :: (FromEndo a, EndoOperatedOn a ~ c) => (a -> b) -> Dual (Endo c) -> b+fromDualEndoWith = (. fromDualEndo)++-- | Same as 'fromDualEndoWith', but deals with @'Dual' 'Endo'@ wrapped inside+-- a 'Functor'.+fromDualEndoWithF+ :: (Functor f, FromEndo a, EndoOperatedOn a ~ c)+ => (f a -> b) -> f (Dual (Endo c)) -> b+fromDualEndoWithF = (. fmap fromDualEndo)++-- | Variant of 'fromEndo' that takes type restriction on the result type @a@+-- as an argument.+fromEndoTo :: FromEndo a => Endo (EndoOperatedOn a) -> proxy a -> a+fromEndoTo e _ = fromEndo e++-- | Variant of 'fromDualEndo' that takes type restriction on the result type+-- @a@ as an argument.+fromDualEndoTo :: FromEndo a => Dual (Endo (EndoOperatedOn a)) -> proxy a -> a+fromDualEndoTo e _ = fromDualEndo e