endo 0.2.0.0 → 0.2.0.1
raw patch · 15 files changed
+158/−34 lines, 15 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- ChangeLog.md +8/−0
- README.md +2/−0
- endo.cabal +4/−3
- example/Example/Config.hs +1/−1
- example/Example/Config/Lens.hs +1/−1
- example/Example/Config/Setters.hs +1/−1
- example/Example1.hs +1/−1
- example/Example2.hs +1/−1
- example/Example3.hs +8/−1
- example/Example4.hs +1/−1
- example/Example5.hs +1/−1
- example/Example6.hs +1/−1
- example/Example7.hs +2/−1
- src/Data/Monoid/Endo.hs +1/−1
- src/Data/Monoid/Endo/Fold.hs +125/−20
ChangeLog.md view
@@ -1,6 +1,14 @@ # ChangeLog / ReleaseNotes +## Version 0.2.0.1++* API documentation ehancements and clarifications.+* Explicit implementation of `aDualEndo` for+ `instance AnEndo a => AnEndo (Maybe a)`.+* Uploaded to [Hackage][]: <http://hackage.haskell.org/package/endo-0.2.0.1>++ ## Version 0.2.0.0 * Default implementation for `anEndo` method of 'AnEndo' type class, which is
README.md view
@@ -1,6 +1,7 @@ # Endo [][Hackage: endo]+[](http://packdeps.haskellers.com/reverse/endo) [][Haskell.org] [][tl;dr Legal: BSD3] @@ -159,6 +160,7 @@ options :: Parser Config options = runIdentityT $ runEndo defaultConfig <$> options' where+ -- All this IdentityT clutter is here to avoid orphan instances. options' :: IdentityT Parser (Endo Config) options' = foldEndo <*> outputOption -- :: IdentityT Parser (Maybe (E Config))
endo.cabal view
@@ -1,5 +1,5 @@ name: endo-version: 0.2.0.0+version: 0.2.0.1 synopsis: Endomorphism utilities. description: Package defines extra functions for 'Data.Monoid.Endo' data type, and also@@ -19,6 +19,7 @@ > options :: Parser Config > options = runIdentityT $ runEndo defaultConfig <$> options' > where+ > -- All this IdentityT clutter is here to avoid orphan instances. > options' :: IdentityT Parser (Endo Config) > options' = foldEndo > <*> outputOption -- :: IdentityT Parser (Maybe (E Config))@@ -45,7 +46,7 @@ license-file: LICENSE author: Peter Trško maintainer: peter.trsko@gmail.com-copyright: (c) 2013-2015 Peter Trško+copyright: (c) 2013-2015, Peter Trško category: Data build-type: Simple cabal-version: >=1.10@@ -113,4 +114,4 @@ source-repository this type: git location: git://github.com/trskop/endo.git- tag: 0.2.0.0+ tag: 0.2.0.1
example/Example/Config.hs view
@@ -3,7 +3,7 @@ -- | -- Module: $HEADER$ -- Description: Simple example of Config data type.--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example/Config/Lens.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Simple setters for Config data type.--- Copyright: (c) 2013-2015 Peter Trško+-- Copyright: (c) 2013-2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example/Config/Setters.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Simple setters for Config data type.--- Copyright: (c) 2013-2015 Peter Trško+-- Copyright: (c) 2013-2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example1.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Example 1--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example2.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Example 2--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example3.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Example 3--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com@@ -13,7 +13,11 @@ module Example3 where +import Control.Monad (guard)+import Data.Bool (not) import Data.Function (($))+import Data.Functor ((<$))+import Data.List (null) import Data.Maybe (Maybe(Just, Nothing)) import Data.Monoid (Endo(appEndo)) import System.IO (FilePath)@@ -33,3 +37,6 @@ example3 = appEndo $ foldEndo &$ setVerbosity Annoying &$ setOutputFile3 "an.out.put"++setOutputFile3':: FilePath -> Maybe (E Config)+setOutputFile3' fp = setOutputFile fp <$ guard (not (null fp))
example/Example4.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Example 4--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example5.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Example 5--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example6.hs view
@@ -4,7 +4,7 @@ -- | -- Module: $HEADER$ -- Description: Example 6--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
example/Example7.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Example 7--- Copyright: (c) 2015 Peter Trško+-- Copyright: (c) 2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com@@ -57,6 +57,7 @@ options :: Parser Config options = runIdentityT $ runEndo defaultConfig <$> options' where+ -- All this IdentityT clutter is here to avoid orphan instances. options' :: IdentityT Parser (Endo Config) options' = foldEndo <*> outputOption -- :: IdentityT Parser (Maybe (E Config))
src/Data/Monoid/Endo.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Utilities for Endo data type.--- Copyright: (c) 2013-2015 Peter Trško+-- Copyright: (c) 2013-2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com
src/Data/Monoid/Endo/Fold.hs view
@@ -23,7 +23,7 @@ -- | -- Module: $HEADER$ -- Description: Generic folding for various endomorphism representations.--- Copyright: (c) 2014, 2015 Peter Trško+-- Copyright: (c) 2014-2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com@@ -35,9 +35,23 @@ module Data.Monoid.Endo.Fold ( -- * Usage Examples- -- $usageExample+ --+ -- | Examples in this section were taken from real live production code,+ -- but they were tamed down a little. - -- ** Using with optparse-applicative+ -- ** Basic Idea+ -- $basicIdea++ -- ** Working With Corner Cases+ -- $workingWithCornerCases++ -- ** Using With Lenses+ -- $lenses++ -- ** Other Usage+ -- $otherUsage++ -- ** Using With optparse-applicative -- $optparseApplicativeExample -- * Generic Endomorphism Folding@@ -151,7 +165,17 @@ -- | Extracts type of a value that is modified by the result. type ResultOperatesOn a - -- | Result type of the whole endomorphism folding.+ -- | Result type of the whole endomorphism folding. It can be used to+ -- restrict the result of 'foldEndo' and 'dualFoldEndoArgs'. Example:+ --+ -- @+ -- -- Type restricted version of 'foldEndo' that forces the result of the+ -- -- whole folding machinery to be \"'Endo' Int\".+ -- myFoldEndo+ -- :: ('Result' args ~ 'Endo' Int, 'FoldEndoArgs' args)+ -- => args -> args+ -- myFoldEndo = 'foldEndo'+ -- @ type Result a foldEndoArgs :: Endo (ResultOperatesOn a) -> a@@ -160,6 +184,9 @@ {-# MINIMAL foldEndoArgs, dualFoldEndoArgs #-} #endif +-- | Recurse along 'FoldEndoArgs' instances if first argument is 'AnEndo'.+-- This instance is actually what makes 'foldEndo' and 'dualFoldEndo'+-- variadic-like. instance ( AnEndo a , FoldEndoArgs r@@ -177,6 +204,10 @@ foldEndoArgs = id dualFoldEndoArgs (Dual e) = e +-- | This basically discards result of folding, in example:+--+-- >>> foldEndo ('n':) ('o':) :: Const () (Endo String)+-- Const () instance (Monoid c, FoldEndoArgs r) => FoldEndoArgs (Const c r) where type ResultOperatesOn (Const c r) = ResultOperatesOn r type Result (Const c r) = Const c (Result r)@@ -195,6 +226,29 @@ foldEndoArgs = Identity . foldEndoArgs dualFoldEndoArgs = Identity . dualFoldEndoArgs +-- | Allows endomorphism folding for endomorphisms wrapped inside 'IO' monad.+-- Examples:+--+-- @+-- 'foldEndo' \<*\> ((++) \<$\> getLine) \<*\> ((++) \<$\> getLine)+-- :: :: ('FoldEndoArgs' r, 'ResultOperatesOn' r ~ String) => IO r+-- @+--+-- In the next example, prefix @ghci\>@ indicates GHCi prompt, @ghci|@ is GHCi+-- continuation prompt, @\<\<\<@ indicates user input and @\>\>\>@ GHCi output.+-- Also, @:{@ and @:}@ is GHCi's way of starting and ending multiline mode,+-- respectively.+--+-- @+-- ghci\> :{+-- ghci| 'Control.Monad.Endo.runEndo' \"\" '<&$>' 'foldEndo'+-- ghci| \<*\> ((++) \<$\> getLine)+-- ghci| \<*\> ((++) \<$\> getLine)+-- ghci| :}+-- \<\<\< alpha+-- \<\<\< bet+-- \>\>\> \"alphabet\"+-- @ instance FoldEndoArgs r => FoldEndoArgs (IO r) where type ResultOperatesOn (IO r) = ResultOperatesOn r type Result (IO r) = IO (Result r)@@ -353,6 +407,33 @@ -- | 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. class AnEndo a where -- | Extract type on which endomorphism operates, e.g. for -- @'Endo' a@ it would be @a@.@@ -392,6 +473,9 @@ 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@@ -734,9 +818,10 @@ -- {{{ Utility Functions ------------------------------------------------------ --- | Variant of function @('Data.Function.$') :: (a -> b) -> a -> b@ from--- "Data.Function" module, but with fixity as @(&) :: a -> (a -> b) -> b@--- function from <http://hackage.haskell.org/package/lens lens package>.+-- | Variant of function @('Data.Function.$') :: (a -> b) -> a -> b@, from+-- "Data.Function" module, but with fixity as+-- @('Data.Function.&') :: a -> (a -> b) -> b@ function from "Data.Function"+-- module (available in base since version 4.8.0.0). (&$) :: (a -> b) -> a -> b f &$ a = f a infixl 1 &$@@ -782,7 +867,7 @@ -- }}} Utility Functions ------------------------------------------------------ --- $usageExample+-- $basicIdea -- -- Lets define simple application @Config@ data type as: --@@ -827,10 +912,15 @@ -- -- 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.+-- 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.++-- $workingWithCornerCases ----- Now, 'System.IO.FilePath' has one pathological case, and that is \"\". There+-- In real applications corner cases arise quite easily, e.g.+-- 'System.IO.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. --@@ -860,6 +950,16 @@ -- '&$' setOutputFile3 \"an.out.put\" -- @ --+-- Great thing about 'Maybe' is the fact that it has+-- 'Control.Applicative.Alternative' and 'Control.Monad.MonadPlus' instances.+-- Using 'Control.Monad.guard' may simplify @setOutputFile3@ in to definition+-- like following:+--+-- @+-- setOutputFile3':: FilePath -> Maybe ('Data.Monoid.Endo.E' Config)+-- setOutputFile3' fp = setOutputFile fp 'Data.Functor.<$' 'Control.Monad.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.@@ -875,22 +975,24 @@ -- 'Control.Applicative.<*>' setOutputFile4 \"an.out.put\" -- @ ----- Notice, that above example uses applicative style. Normally when using this--- style, for setting record values, one needs to keep in sync order of--- constructor arguments and order of operations. Using 'foldEndo' (and its+-- Notice, that above example uses applicative style. Normally, when using this+-- style for setting record values, one needs to keep in sync the order of+-- constructor arguments, and order of operations. Using 'foldEndo' (and its -- dual 'dualFoldEndo') doesn't have this restriction.++-- $lenses ----- Instead of setter functions one may want to use lenses (in terms of--- <http://hackage.haskell.org/package/lens lens package>):+-- Instead of setter functions one may want to use lenses. In this example we+-- use types from <http://hackage.haskell.org/package/lens lens package>, but+-- definitions use function from+-- <http://hackage.haskell.org/package/between between package>: -- -- @ -- verbosity :: Lens' Config Verbosity--- verbosity =--- _verbosity 'Data.Function.Between.~@@^>' \\s b -> s{_verbosity = b}+-- verbosity = _verbosity 'Data.Function.Between.~@@^>' \\s b -> s{_verbosity = b} -- -- outputFile :: Lens' Config FilePath--- outputFile =--- _outputFile 'Data.Function.Between.~@@^>' \\s b -> s{_outputFile = b}+-- outputFile = _outputFile 'Data.Function.Between.~@@^>' \\s b -> s{_outputFile = b} -- @ -- -- Now setting values of @Config@ would look like:@@ -901,6 +1003,8 @@ -- '&$' verbosity .~ Annoying -- '&$' outputFile .~ \"an.out.put\" -- @++-- $otherUsage -- -- Probably one of the most interesting things that can be done with this -- module is following:@@ -932,6 +1036,7 @@ -- options :: Parser Config -- options = 'Control.Monad.Trans.Identity.runIdentityT' $ 'Control.Monad.Endo.runEndo' defaultConfig \<$\> options' -- where+-- -- All this IdentityT clutter is here to avoid orphan instances. -- options' :: 'IdentityT' Parser ('Endo' Config) -- options' = 'foldEndo' -- \<*\> outputOption -- :: IdentityT Parser (Maybe (E Config))