between 0.10.0.0 → 0.11.0.0
raw patch · 9 files changed
+1165/−44 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Function.Between.Lazy: (~$$~) :: b -> a -> (a -> b -> r) -> r
+ Data.Function.Between.Lazy: (~$~) :: a -> b -> (a -> b -> r) -> r
+ Data.Function.Between.Lazy: inbetween :: a -> b -> (a -> b -> r) -> r
+ Data.Function.Between.Lazy: le :: Functor f => PreLens ((a -> f b) -> s -> f t) s t a b -> (a -> f b) -> s -> f t
+ Data.Function.Between.Lazy: preIso :: (s -> a) -> (b -> t) -> PreIso r s t a b
+ Data.Function.Between.Lazy: preIso' :: (b -> t) -> (s -> a) -> PreIso r s t a b
+ Data.Function.Between.Lazy: preIsoToPreLens :: PreIso r s t a b -> PreLens r s t a b
+ Data.Function.Between.Lazy: preLens :: (s -> b -> t) -> (s -> a) -> PreLens r s t a b
+ Data.Function.Between.Lazy: preLens' :: (s -> a) -> (s -> b -> t) -> PreLens r s t a b
+ Data.Function.Between.Lazy: prePrism :: (b -> t) -> (s -> Either t a) -> PrePrism r s t a b
+ Data.Function.Between.Lazy: prePrism' :: (b -> s) -> (s -> Maybe a) -> PrePrism r s s a b
+ Data.Function.Between.Lazy: type PreIso r s t a b = ((b -> t) -> (s -> a) -> r) -> r
+ Data.Function.Between.Lazy: type PreIso' r s a = PreIso r s s a a
+ Data.Function.Between.Lazy: type PreLens r s t a b = ((b -> s -> t) -> (s -> a) -> r) -> r
+ Data.Function.Between.Lazy: type PreLens' r s a = PreLens r s s a a
+ Data.Function.Between.Lazy: type PrePrism r s t a b = ((b -> t) -> (s -> Either t a) -> r) -> r
+ Data.Function.Between.Lazy: type PrePrism' r s a = PrePrism r s s a a
+ Data.Function.Between.Lazy: withIn :: ((a -> b -> r) -> r) -> (a -> b -> r) -> r
+ Data.Function.Between.Lazy: withReIn :: ((b -> a -> r) -> r) -> (a -> b -> r) -> r
+ Data.Function.Between.Strict: (~$$~) :: b -> a -> (a -> b -> r) -> r
+ Data.Function.Between.Strict: (~$~) :: a -> b -> (a -> b -> r) -> r
+ Data.Function.Between.Strict: inbetween :: a -> b -> (a -> b -> r) -> r
+ Data.Function.Between.Strict: le :: Functor f => PreLens ((a -> f b) -> s -> f t) s t a b -> (a -> f b) -> s -> f t
+ Data.Function.Between.Strict: preIso :: (s -> a) -> (b -> t) -> PreIso r s t a b
+ Data.Function.Between.Strict: preIso' :: (b -> t) -> (s -> a) -> PreIso r s t a b
+ Data.Function.Between.Strict: preIsoToPreLens :: PreIso r s t a b -> PreLens r s t a b
+ Data.Function.Between.Strict: preLens :: (s -> b -> t) -> (s -> a) -> PreLens r s t a b
+ Data.Function.Between.Strict: preLens' :: (s -> a) -> (s -> b -> t) -> PreLens r s t a b
+ Data.Function.Between.Strict: prePrism :: (b -> t) -> (s -> Either t a) -> PrePrism r s t a b
+ Data.Function.Between.Strict: prePrism' :: (b -> s) -> (s -> Maybe a) -> PrePrism r s s a b
+ Data.Function.Between.Strict: type PreIso r s t a b = ((b -> t) -> (s -> a) -> r) -> r
+ Data.Function.Between.Strict: type PreIso' r s a = PreIso r s s a a
+ Data.Function.Between.Strict: type PreLens r s t a b = ((b -> s -> t) -> (s -> a) -> r) -> r
+ Data.Function.Between.Strict: type PreLens' r s a = PreLens r s s a a
+ Data.Function.Between.Strict: type PrePrism r s t a b = ((b -> t) -> (s -> Either t a) -> r) -> r
+ Data.Function.Between.Strict: type PrePrism' r s a = PrePrism r s s a a
+ Data.Function.Between.Strict: withIn :: ((a -> b -> r) -> r) -> (a -> b -> r) -> r
+ Data.Function.Between.Strict: withReIn :: ((b -> a -> r) -> r) -> (a -> b -> r) -> r
+ Data.Function.Between.Strict.Internal: (.) :: (b -> c) -> (a -> b) -> a -> c
+ Data.Function.Between.Strict.Internal: flip :: (a -> b -> c) -> b -> a -> c
+ Data.Function.Between.Types: type PreIso r s t a b = ((b -> t) -> (s -> a) -> r) -> r
+ Data.Function.Between.Types: type PreIso' r s a = PreIso r s s a a
+ Data.Function.Between.Types: type PreLens r s t a b = ((b -> s -> t) -> (s -> a) -> r) -> r
+ Data.Function.Between.Types: type PreLens' r s a = PreLens r s s a a
+ Data.Function.Between.Types: type PrePrism r s t a b = ((b -> t) -> (s -> Either t a) -> r) -> r
+ Data.Function.Between.Types: type PrePrism' r s a = PrePrism r s s a a
Files
- ChangeLog.md +21/−2
- LICENSE +1/−1
- README.md +10/−0
- between.cabal +10/−5
- src/Data/Function/Between.hs +273/−10
- src/Data/Function/Between/Lazy.hs +330/−6
- src/Data/Function/Between/Strict.hs +351/−20
- src/Data/Function/Between/Strict/Internal.hs +48/−0
- src/Data/Function/Between/Types.hs +121/−0
ChangeLog.md view
@@ -1,14 +1,33 @@ # ChangeLog / ReleaseNotes +## Version 0.11.0.0++* New function application combinators (**new**):+ * `inbetween :: a -> b -> (a -> b -> r) -> r`+ * `(~$~) :: a -> b -> (a -> b -> r) -> r`+ * `(~$$~) :: b -> a -> (a -> b -> r) -> r`+ * `withIn :: ((a -> b -> r) -> r) -> (a -> b -> r) -> r`+ * `withReIn :: ((b -> a -> r) -> r) -> (a -> b -> r) -> r`+* Precursors to `Iso`, `Lens` and `Prism` (**new**):+ * `type PreIso r s t a b = ((b -> t) -> (s -> a) -> r) -> r`+ * `type PreIso' r s a = PreIso r s s a a`+ * `type PreLens r s t a b = ((b -> s -> t) -> (s -> a) -> r) -> r`+ * `type PreLens' r s a = PreLens r s s a a`+ * `type PrePrism r s t a b = ((b -> t) -> (s -> Either t a) -> r) -> r`+ * `type PrePrism' r s a = PrePrism r s s a a`+* Uploaded to Hackage: http://hackage.haskell.org/package/between-0.11.0.0++ ## Version 0.10.0.0 * Original implementation moved to module `Data.Function.Between.Lazy` and is- now reexported by `Data.Function.Between`. (new)+ now reexported by `Data.Function.Between`. (**new**) * Implementation of strict variants of all functions defined in `Data.Function.Between.Lazy` module. These new functions use `(f . g) x = f '$!' g '$!' x` as definition for function composition where- `$!` is strict application. (new)+ `$!` is strict application. (**new**)+* Uploaded to Hackage: http://hackage.haskell.org/package/between-0.10.0.0 ## Version 0.9.0.2
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
@@ -2,6 +2,7 @@ ======= [][Hackage: between]+[](http://packdeps.haskellers.com/reverse/between) [][Haskell.org] [][tl;dr Legal: BSD3] @@ -56,6 +57,12 @@ Pass additional warning flags to GHC. +License+-------++The BSD 3-Clause License, see [LICENSE][] file for details.++ Contributions ------------- @@ -75,3 +82,6 @@ [tl;dr Legal: BSD3]: https://tldrlegal.com/license/bsd-3-clause-license-%28revised%29 "BSD 3-Clause License (Revised)"+[LICENSE]:+ https://github.com/trskop/between/blob/master/LICENSE+ "License of between package."
between.cabal view
@@ -1,5 +1,5 @@ name: between-version: 0.10.0.0+version: 0.11.0.0 synopsis: Function combinator "between" and derived combinators description: It turns out that this combinator@@ -9,8 +9,8 @@ is a powerful thing. It was abstracted from following (commonly used) pattern @f . h . g@ where @f@ and @g@ are fixed. .- This library not only define @~\@~@ combinator, but also some derived- combinators that can help us to easily define a lot of things including+ This library not only defines @~\@~@ combinator, but also some derived+ combinators that can help us easily define a lot of things including lenses. See <http://hackage.haskell.org/package/lens lens package> for detais on what lenses are. .@@ -33,11 +33,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.8 +-- 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+ extra-source-files: README.md , ChangeLog.md@@ -53,6 +56,8 @@ Data.Function.Between , Data.Function.Between.Lazy , Data.Function.Between.Strict+ , Data.Function.Between.Strict.Internal+ , Data.Function.Between.Types build-depends: base > 3 && < 5 ghc-options: -Wall@@ -70,4 +75,4 @@ source-repository this type: git location: git://github.com/trskop/between.git- tag: v0.10.0.0+ tag: v0.11.0.0
src/Data/Function/Between.hs view
@@ -3,7 +3,7 @@ -- | -- Module: $HEADER$ -- Description: Function combinator "between" and its variations.--- Copyright: (c) 2013-2015 Peter Trsko+-- Copyright: (c) 2013-2016, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com@@ -16,15 +16,17 @@ -- overkill for some purposes. -- -- This library describes simple and composable combinators that are built on--- top of very basic concept:+-- top of few very basic concepts. First one is: ----- @f . h . g@+-- @\\h -> f . h . g@ ----- Where @f@ and @g@ are fixed. It is possible to reduce it to just:+-- Where @f@ and @g@ are fixed and @h@ is a free variable. It is possible to+-- reduce it to just: -- -- @(f .) . (. g)@ ----- Which is the core pattern used by all functions defined in this module.+-- Which is one of the core pattern used by all related functions defined in+-- this module. -- -- Trying to generalize this pattern further ends as -- @(f 'Data.Functor.<$>') '.' ('Data.Functor.<$>' g)@, where@@ -39,7 +41,32 @@ -- -- Which doesn't give us much more power. Instead of going for such -- generalization we kept the original @((f .) . (. g))@ which we named--- 'between' or '~@~' in its infix form.+-- 'between' or '~@~' in its infix form. There are other possible+-- generalizations possible, in example by using 'Control.Category..' from+-- "Control.Category" or by using composition from @Semigroupoid@ class, but+-- that requires dependency on+-- <https://hackage.haskell.org/package/semigroups semigroupoids> package.+--+-- Second concept\/pattern exploited in this package is infix function+-- application with two arguments:+--+-- @+-- \\(<>) -> a <> b+-- @+--+-- Where @a@ and @b@ are fixed and @<>@ is a free variable. This library+-- defines 'inbetween' operator (also called '~$~', in its infix form) that+-- embodies mentioned pattern:+--+-- @+-- 'inbetween' :: a -> b -> (a -> b -> r) -> r+-- 'inbetween' a b f = a ``f`` b+-- @+--+-- @+-- ('~$~') :: a -> b -> (a -> b -> r) -> r+-- (a '~$~' b) (<>) = a <> b+-- @ module Data.Function.Between ( -- | This module reexports "Data.Function.Between.Lazy" that uses standard@@ -60,6 +87,14 @@ -- -- $lenses + -- * Using With Lenses+ --+ -- $withLenses++ -- * Precursors to Iso, Lens and Prism+ --+ -- $precursorsToIsoLensAndPrism+ -- * Related Work -- -- | There are other packages out there that provide similar combinators.@@ -138,7 +173,7 @@ -- Which allows us to interpret '~@~' in terms like \"apply this function to -- the n-th argument before passing it to the function @f@\". We just have to -- count the arguments backwards. In example if want to apply function @g@ to--- third argument, but no other then we can use:+-- third argument, but no other, then we can use: -- -- @ -- \\g f -> ('Data.Function.id' '~@~' g '~@~' 'Data.Function.id' '~@~' 'Data.Function.id') f@@ -295,7 +330,7 @@ -- t = T '<~@~' fromT -- @ ----- Lets define lenses for generic data type, e.g. something like:+-- Now, lets define lenses for generic data type, e.g. something like: -- -- @ -- data D a b = D {_x :: a, _y :: b}@@ -373,6 +408,234 @@ -- <http://hackage.haskell.org/package/transformers transformers package> or -- in base >= 4.8. +-- $withLenses+--+-- Leses are basically just functions with a nice trick to them. If you look+-- at the core pattern used in <https://hackage.haskell.org/package/lens lens>+-- library is:+--+-- @+-- type Optical p q f s t a b = p a (f b) -> q s (f t)+-- @+--+-- Which is just a function @c -> d@ where @c = p a (f b)@ and @d = q s (f t)@.+-- In most common situations @p@ and @q@ are instantiated to be @->@ making+-- the @Optical@ type colapse in to something more specific:+--+-- @+-- type LensLike f s t a b = (a -> f b) -> s -> f t+-- @+--+-- Where @f@ is some instance of 'Functor' and that is how we get @Lens@, which+-- is just:+--+-- @+-- type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t+-- @+--+-- These lenses are called /Laarhoven Lenses/, after /Twan van Laarhoven/ who+-- introduced them in+-- <http://www.twanvl.nl/blog/haskell/cps-functional-references CPS based functional references>+-- article.+--+-- We can choose even stronger constraints then 'Functor', in example+-- 'Control.Applicative.Applicative', then we get a @Traversal@, and, of+-- course, it doesn't end with it, since there is a lot more to choose from.+--+-- What is important, in the above /lens/ pattern, is that it's a function that+-- can be composed using function composition ('.') operator (remember that+-- it's just a function @c -> d@). As a consequence 'between' can be used as+-- well. Small example:+--+-- >>> (1, ((2, 3), (4, 5))) ^. (_2 ~@~ _2) _1+-- 3+-- >>> (1, ((2, 3), (4, 5))) ^. (_2 ~@~ _2) _2+-- 5+--+-- This shows us that '~@~' can be used to compose two lenses, or other+-- abstractions from that library, but with a hole in between, where another+-- one can be injected.+--+-- Lets imagine following example:+--+-- @+-- data MyData f a b = MyData+-- { _foo :: f a+-- , _bar :: f b+-- }+-- @+--+-- Lets have lenses for @MyData@:+--+-- @+-- foo :: Lens (MyData h a b) (MyData h a' b) (h a) (h a')+-- bar :: Lens (MyData h a b) (MyData h a b') (h b) (h b')+-- @+--+-- Following instance of data type @MyData@ is what our example will be based+-- upon:+--+-- @+-- -- We use type proxy to instantiate \'h\' in to concrete functor.+-- myData+-- :: 'Control.Applicative.Applicative' h+-- => proxy h+-- -> MyData h (Int, Int) (String, String)+-- myData _ = MyData+-- { _foo = pure (1, 2)+-- , _bar = pure ("hello", "world")+-- }+-- @+--+-- We don't know exactly what @h@ will be instantiated to, but we can already+-- provide following lenses:+--+-- @+-- foo1in+-- :: (Field1 s t a1 b1, 'Functor' f)+-- => LensLike f (h a) (h a') s t+-- -> LensLike f (MyData h a b) (MyData h a' b) a1 b1+-- foo1in = foo '~@~' _1+--+-- foo2in+-- :: (Field2 s t a1 b1, 'Functor' f)+-- => LensLike f (h a) (h a') s t+-- -> LensLike f (MyData h a b) (MyData h a' b) a1 b1+-- foo2in = foo '~@~' _2+--+-- bar1in+-- :: (Field1 s t a1 b1, 'Functor' f)+-- => LensLike f (h b) (h b') s t+-- -> LensLike f (MyData h a b) (MyData h a b') a1 b1+-- bar1in = bar '~@~' _1+--+-- bar2in+-- :: (Field2 s t a1 b1, 'Functor' f)+-- => LensLike f (h b) (h b') s t+-- -> LensLike f (MyData h a b) (MyData h a b') a1 b1+-- bar2in = bar '~@~' _2+-- @+--+-- Don't get scared by the type signatures, just focus on the pattern here.+--+-- >>> myData (Proxy :: Proxy ((,) ())) ^. foo1in _2+-- 1+-- >>> myData (Proxy :: Proxy ((,) ())) ^. foo2in _2+-- 2+-- >>> myData (Proxy :: Proxy Maybe) ^. bar1in _Just+-- "hello"+-- >>> myData (Proxy :: Proxy Maybe) ^. bar2in _Just+-- "world"++-- $precursorsToIsoLensAndPrism+--+-- When it comes to standard data types, then at the hart of every @Iso@,+-- @Lens@ and @Prism@, lies a simple trick. A hole is inserted between getter+-- (i.e. destructor) function and setter (i.e. constructor) function.+-- Difference between various constructs in e.g.+-- <https://hackage.haskell.org/package/lens lens> library is the+-- specialization of that hole, which in turn constraints type signature a+-- little bit.+--+-- Example:+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- x :: Lens' Coords2D Int+-- x f s = setter s 'Data.Functor.<$>' f (getter s)+-- where+-- getter = _x+-- setter s b = s{_x = b}+-- @+--+-- As we can see, in the above example, there is a function function inserted+-- in between @getter@ and @setter@ functions. That function contains an+-- unknown function @f@.+--+-- If we gather all the code in between @getter@ and @setter@ functions and put+-- in to one place, then we would get:+--+-- @+-- x :: Lens' Coords2D Int+-- x = setter \`f\` getter+-- where+-- getter = _x+-- setter s b = s{_x = b}+-- f set get h s = set s 'Data.Functor.<$>' h (get h)+-- @+--+-- Now we can see that the original hole (function @f@) has moved little bit+-- further down and is now called @h@. Function @f@ now is a /Lens/ smart+-- constructor that takes getter and setter and creates a /Lens/. This leads us+-- to a question. What would happen if we won't specialize @f@, at all, and+-- leave it to a user to decide what it should be? This is what we would get:+--+-- @+-- preX :: ((Coords2D -> Int) -> (Coords2D -> Int -> Coords2D) -> r) -> r+-- preX f = _x \`f\` \\s b -> s{_x = b}+-- @+--+-- Now we can move things arount a bit:+--+-- @+-- preX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- preX f = (\\b s -> s{_x = b}) \`f\` _x+-- @+--+-- This can also be rewritten to use '~$~' combinator:+--+-- @+-- preX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- preX = (\\b s -> s{_x = b}) '~$~' _x+-- @+--+-- Or even using its flipped variant '~$$~':+--+-- @+-- preX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- preX = _x '~$$~' \\b s -> s{_x = b}+-- @+--+-- We call such function a 'PreLens', since it is actually a precursor to a+-- 'Lens'.+--+-- @+-- preX :: 'PreLens'' r Coords2D Int+-- preX = _x '~$$~' \\b s -> s{_x = b}+-- @+--+-- It is also function with the most generic type signature of a function that+-- is capable of creating a lens from getter and setter, if @f@ is specialized+-- appropriately:+--+-- @+-- x :: Lens' Coords2D Int+-- x = preX (('<^@~') . 'flip')+-- @+--+-- Notice that @preX@, in the above code snipped, got specialized in to:+--+-- @+-- preX :: 'PreLens'' (Lens' Coords2D Int) Coords2D Int+-- @+--+-- Function @preX@ takes a /lens/ smart constructor, regardles of what /lens/+-- kind that constructor produces. It can be /Laarhoven Lens/, /Store+-- Comonad-coalgebra/ or any other representation. As a special case it can+-- also take a function that gets either getter or setter, or even a function+-- that combines those functions with others.+--+-- This trick of putting a hole between constructor (anamorphism) and+-- destructor (catamorphism) is also the reason why Laarhoven's Lenses can be+-- introduced as a generalization of <https://wiki.haskell.org/Zipper zipper>+-- idiom. For more information see also:+--+-- * <https://www.fpcomplete.com/user/psygnisfive/from-zipper-to-lens From Zipper To Lens>+--+-- * <http://www.twanvl.nl/blog/haskell/cps-functional-references CPS based functional references>,+-- introduction of Laarhoven's Lenses.+ -- $profunctors -- -- You may have noticed similarity between:@@ -388,7 +651,7 @@ -- @ -- -- If you also consider that there is also @instance Profunctor (->)@, then--- 'between' becomes specialized @dimap@ for @Profunctor (->)@.+-- 'between' becomes specialized flipped @dimap@ for @Profunctor (->)@. -- -- Profunctors are a powerful abstraction and Edward Kmett's implementation -- also includes low level optimizations that use the coercible feature of GHC.@@ -398,7 +661,7 @@ -- $pointless-fun -- -- Package <https://hackage.haskell.org/package/pointless-fun pointless-fun>--- provides few similar combinators then 'between' in both strict and lazy+-- provides few similar combinators, to 'between', in both strict and lazy -- variants: -- -- @
src/Data/Function/Between/Lazy.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Lazy function combinator "between" and its variations.--- Copyright: (c) 2013-2015 Peter Trško+-- Copyright: (c) 2013-2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com@@ -16,7 +16,7 @@ -- Prior to version 0.10.0.0 functions defined in this module were directly -- in "Data.Function.Between". ----- /Since version 0.10.0.0./+-- /Module available since version 0.10.0.0./ module Data.Function.Between.Lazy ( -- * Between Function Combinator@@ -27,7 +27,7 @@ , (~@~) , (~@@~) - -- * Derived Combinators+ -- ** Derived Combinators -- -- | Combinators that either further parametrise @f@ or @g@ in -- @f '.' g '.' h@, or apply '~@~' more then once.@@ -65,13 +65,62 @@ , (^@^>) , (<^@@^)++ -- * In-Between Function Application Combinator+ --+ -- | Captures common pattern of @\\f -> (a \`f\` b)@ where @a@ and @b@ are+ -- fixed parameters. It doesn't look impressive untill one thinks about @a@+ -- and @b@ as functions.+ --+ -- /Since version 0.11.0.0./+ , inbetween+ , (~$~)+ , (~$$~)++ , withIn+ , withReIn++ -- * Precursors to Iso, Lens and Prism+ --+ -- | /Since version 0.11.0.0./++ -- ** PreIso+ , PreIso+ , PreIso'+ , preIso+ , preIso'++ -- ** PreLens+ , PreLens+ , PreLens'+ , preLens+ , preLens'+ , preIsoToPreLens+ , le++ -- ** PrePrism+ , PrePrism+ , PrePrism'+ , prePrism+ , prePrism' ) where +import Data.Either (Either(Left, Right)) import Data.Functor (Functor(fmap))-import Data.Function ((.), flip)+import Data.Function ((.), ($), const, flip, id)+import Data.Maybe (Maybe, maybe) +import Data.Function.Between.Types+ ( PreIso+ , PreIso'+ , PreLens+ , PreLens'+ , PrePrism+ , PrePrism'+ ) + -- | Core combinator of this module and we build others on top of. It also has -- an infix form '~@~' and flipped infix form '~@@~'. --@@ -224,7 +273,7 @@ g <~@@~> f = fmap f `between` fmap g infix 8 <~@@~> --- | Apply fmap to first argument of '~@~'. Dual to '~@~>' which applies+-- | Apply 'fmap' to first argument of '~@~'. Dual to '~@~>' which applies -- 'fmap' to second argument. -- -- Defined as:@@ -259,7 +308,7 @@ (~@@~>) = flip (<~@~) infixr 8 ~@@~> --- | Apply fmap to second argument of '~@~'. Dual to '<~@~' which applies+-- | Apply 'fmap' to second argument of '~@~'. Dual to '<~@~' which applies -- 'fmap' to first argument. -- -- Defined as:@@ -416,3 +465,278 @@ => (a -> b -> c) -> (a -> d -> e) -> (f c -> d) -> a -> f b -> e (<^@@^) = flip (^@^>) infix 8 <^@@^++-- {{{ In-Between Function Application Combinator -----------------------------++-- | Prefix version of common pattern:+--+-- @+-- \\f -> a \`f\` b+-- @+--+-- Where @a@ and @b@ are fixed parameters. There is also infix version named+-- '~$~'. This function is defined as:+--+-- @+-- 'inbetween' a b f = f a b+-- @+--+-- Based on the above definition one can think of it as a variant function+-- application that deals with two arguments, where in example+-- 'Data.Function.$' only deals with one.+--+-- /Since version 0.11.0.0./+inbetween :: a -> b -> (a -> b -> r) -> r+inbetween a b f = f a b+infix 8 `inbetween`++-- | Infix version of common pattern:+--+-- @+-- \\f -> a \`f\` b+-- @+--+-- Where @a@ and @b@ are fixed parameters. There is also prefix version named+-- 'inbetween'.+--+-- /Since version 0.11.0.0./+(~$~) :: a -> b -> (a -> b -> r) -> r+(~$~) = inbetween+infix 8 ~$~++-- | Infix version of common pattern:+--+-- @+-- \\f -> a \`f\` b -- Notice the order of \'a\' and \'b\'.+-- @+--+-- /Since version 0.11.0.0./+(~$$~) :: b -> a -> (a -> b -> r) -> r+(b ~$$~ a) f = f a b+infix 8 ~$$~++-- | Construct a function that encodes idiom:+--+-- @+-- \\f -> a \`f\` b -- Notice the order of \'b\' and \'a\'.+-- @+--+-- Function 'inbetween' can be redefined in terms of 'withIn' as:+--+-- @+-- a \``inbetween`\` b = 'withIn' 'Data.Function.$' \\f -> a \`f\` b+-- @+--+-- On one hand you can think of this function as a specialized 'id' function+-- and on the other as a function application 'Data.Function.$'. All the+-- following definitions work:+--+-- @+-- 'withIn' f g = f g+-- 'withIn' = 'id'+-- 'withIn' = ('Data.Function.$')+-- @+--+-- Usage examples:+--+-- @+-- newtype Foo a = Foo a+--+-- inFoo :: ((a -> Foo a) -> (Foo t -> t) -> r) -> r+-- inFoo = 'withIn' '$' \\f ->+-- Foo \`f\` \\(Foo a) -> Foo+-- @+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- inX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- inX = 'withIn' '$' \\f ->+-- (\\b s -> s{_x = b}) \`f\` _x+-- @+--+-- /Since version 0.11.0.0./+withIn :: ((a -> b -> r) -> r) -> (a -> b -> r) -> r+withIn = id++-- | Construct a function that encodes idiom:+--+-- @+-- \\f -> b \`f\` a -- Notice the order of \'b\' and \'a\'.+-- @+--+-- Function '~$$~' can be redefined in terms of 'withReIn' as:+--+-- @+-- b '~$$~' a = 'withReIn' '$' \\f -> b \`f\` a+-- @+--+-- As 'withIn', but the function is flipped before applied. All of the+-- following definitions work:+--+-- @+-- 'withReIn' f g = f ('flip' g)+-- 'withReIn' = ('.' 'flip')+-- @+--+-- Usage examples:+--+-- @+-- newtype Foo a = Foo a+--+-- inFoo :: ((a -> Foo a) -> (Foo t -> t) -> r) -> r+-- inFoo = 'withReIn' '$' \\f ->+-- (\\(Foo a) -> Foo) \`f\` Foo+-- @+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- inX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- inX = 'withReIn' '$' \\f ->+-- _x \`f\` \\b s -> s{_x = b}+-- @+--+-- /Since version 0.11.0.0./+withReIn :: ((b -> a -> r) -> r) -> (a -> b -> r) -> r+withReIn = (. flip)++-- {{{ PreIso -----------------------------------------------------------------++-- | Construct a 'PreIso'; this function similar to /Iso/ constructor function+-- from /lens/ package:+--+-- @+-- iso :: (s -> a) -> (b -> t) -> Iso s t a b+-- @+--+-- Usage example:+--+-- @+-- data Foo a = Foo a+--+-- preFoo :: 'PreIso' r (Foo a) (Foo b) a b+-- preFoo = Foo \``preIso`\` \\(Foo a) -> a+-- @+preIso :: (s -> a) -> (b -> t) -> PreIso r s t a b+preIso = (~$$~)+{-# INLINE preIso #-}++-- | Flipped variant of 'preIso'.+--+-- Usage example:+--+-- @+-- data Foo a = Foo {_getFoo :: a}+--+-- preFoo :: 'PreIso' r (Foo a) (Foo b) a b+-- preFoo = _getFoo \``preIso'`\` Foo+-- @+preIso' :: (b -> t) -> (s -> a) -> PreIso r s t a b+preIso' = inbetween+{-# INLINE preIso' #-}++-- }}} PreIso -----------------------------------------------------------------+-- {{{ PreLens ----------------------------------------------------------------++-- | Construct a 'PreLens'; this function is similar to /Lens/ constructor+-- function from /lens/ package:+--+-- @+-- lens :: (s -> b -> t) -> (s -> a) -> Lens' s t a b+-- @+--+-- Usage example:+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- preX :: PreLens' r Coords2D Int+-- preX = (\\s b -> s{_x = b}) \``preLens`\` _x+-- @+preLens :: (s -> b -> t) -> (s -> a) -> PreLens r s t a b+preLens setter getter = flip setter ~$~ getter+{-# INLINE preLens #-}++-- | Flipped version of 'preLens' that takes getter first and setter second.+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- preX :: PreLens' r Coords2D Int+-- preX = _x \``preLens'`\` \\s b -> s{_x = b}+-- @+preLens' :: (s -> a) -> (s -> b -> t) -> PreLens r s t a b+preLens' = flip preLens+{-# INLINE preLens' #-}++-- | Construct a @Lens@ out of a 'PreLens'.+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- preX :: PreLens' r Coords2D Int+-- preX = _x \``preLens'`\` \\s b -> s{_x = b}+--+-- x :: Lens' Coords2D Int+-- x = 'le' preX+-- @+le :: Functor f+ => PreLens ((a -> f b) -> s -> f t) s t a b+ -> (a -> f b) -> s -> f t+le = ($ ((<^@~) . flip))+{-# INLINE le #-}++-- }}} PreLens ----------------------------------------------------------------+-- {{{ PrePrism ---------------------------------------------------------------++-- | Constract a 'PrePrism'; this function is similar to /Prism/ constructor+-- function from /lens/ package:+--+-- @+-- prism :: (b -> t) -> (s -> 'Either' t a) -> Prism s t a b+-- @+--+-- Usage example:+--+-- @+-- {-\# LANGUAGE LambdaCase \#-}+-- data Sum a b = A a | B b+--+-- preA :: 'PrePrism' r (Sum a c) (Sum b c) a b+-- preA = 'prePrism' A '$' \\case+-- A a -> 'Right' a+-- B b -> 'Left' (B b)+-- @+prePrism :: (b -> t) -> (s -> Either t a) -> PrePrism r s t a b+prePrism = inbetween+{-# INLINE prePrism #-}++-- | Simplified construction of 'PrePrism', which can be used in following+-- situations:+--+-- * Constructing /Prism/ for types isomorphic to 'Maybe' or+--+-- * when using 'Data.Typeable.cast' operation, or similar, which either+-- returns what you want or 'Data.Maybe.Nothing'.+--+-- Alternative type signature of this function is also:+--+-- @+-- 'prePrism'' :: 'PreIso' r s s ('Maybe' a) b -> 'PrePrism' r s s a b+-- @+prePrism' :: (b -> s) -> (s -> Maybe a) -> PrePrism r s s a b+prePrism' ana cata = ana ~$~ \s -> maybe (Left s) Right (cata s)+{-# INLINE prePrism' #-}++-- | Convert 'PreIso' in to 'PreLens' by injecting const to a setter function.+--+-- @+-- 'preIsoToPreLens' aPreIso f = aPreIso '$' \\fbt fsa -> 'const' fbt \`f\` fsa+-- @+preIsoToPreLens :: PreIso r s t a b -> PreLens r s t a b+preIsoToPreLens aPreIso f = aPreIso $ \fbt fsa -> (const . fbt) `f` fsa+{-# INLINE preIsoToPreLens #-}++-- }}} PrePrism ---------------------------------------------------------------+-- }}} In-Between Function Application Combinator -----------------------------
src/Data/Function/Between/Strict.hs view
@@ -2,7 +2,7 @@ -- | -- Module: $HEADER$ -- Description: Strict function combinator "between" and its variations.--- Copyright: (c) 2013-2015 Peter Trsko+-- Copyright: (c) 2013-2015, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com@@ -20,18 +20,18 @@ -- (f . g) x = f '$!' g '$!' x -- @ ----- /Since version 0.10.0.0./+-- /Module available since version 0.10.0.0./ module Data.Function.Between.Strict ( -- * Between Function Combinator -- -- | Captures common pattern of @\\g -> (f . g . h)@ where @f@ and @h@- -- are fixed parameters.+ -- are fixed parameters and @(.)@ is strict function composition. between , (~@~) , (~@@~) - -- * Derived Combinators+ -- ** Derived Combinators -- -- | Combinators that either further parametrise @f@ or @g@ in -- @f . g . h@, or apply '~@~' more then once.@@ -69,28 +69,64 @@ , (^@^>) , (<^@@^)++ -- * In-Between Function Application Combinator+ --+ -- | Captures common pattern of @\\f -> (a \`f\` b)@ where @a@ and @b@ are+ -- fixed parameters. It doesn't look impressive untill one thinks about @a@+ -- and @b@ as functions.+ --+ -- /Since version 0.11.0.0./+ , inbetween+ , (~$~)+ , (~$$~)++ , withIn+ , withReIn++ -- * Precursors to Iso, Lens and Prism+ --+ -- | /Since version 0.11.0.0./++ -- ** PreIso+ , PreIso+ , PreIso'+ , preIso+ , preIso'++ -- ** PreLens+ , PreLens+ , PreLens'+ , preLens+ , preLens'+ , preIsoToPreLens+ , le++ -- ** PrePrism+ , PrePrism+ , PrePrism'+ , prePrism+ , prePrism' ) where import Prelude (($!)) +import Data.Either (Either(Left, Right))+import Data.Function (const) import Data.Functor (Functor(fmap))+import Data.Maybe (Maybe, maybe) +import Data.Function.Between.Strict.Internal ((.), flip)+import Data.Function.Between.Types+ ( PreIso+ , PreIso'+ , PreLens+ , PreLens'+ , PrePrism+ , PrePrism'+ ) --- | Strict variant of function composition. Defined as:------ @--- (f . g) x = f '$!' g '$!' x--- @------ Note: this function should not be exported. There are packages out there--- that provide it and without name clashes.------ /Since version 0.10.0.0./-(.) :: (b -> c) -> (a -> b) -> a -> c-(f . g) x = f $! g $! x-infixr 9 .-{-# INLINE (.) #-} -- | Core combinator of this module and we build others on top of. It also has -- an infix form '~@~' and flipped infix form '~@@~'.@@ -257,7 +293,7 @@ g <~@@~> f = fmap f `between` fmap g infix 8 <~@@~> --- | Apply fmap to first argument of '~@~'. Dual to '~@~>' which applies+-- | Apply 'fmap' to first argument of '~@~'. Dual to '~@~>' which applies -- 'fmap' to second argument. -- -- Defined as:@@ -296,7 +332,7 @@ g ~@@~> f = f <~@~ g infixr 8 ~@@~> --- | Apply fmap to second argument of '~@~'. Dual to '<~@~' which applies+-- | Apply 'fmap' to second argument of '~@~'. Dual to '<~@~' which applies -- 'fmap' to first argument. -- -- Defined as:@@ -473,3 +509,298 @@ => (a -> b -> c) -> (a -> d -> e) -> (f c -> d) -> a -> f b -> e g <^@@^ f = f ^@^> g infix 8 <^@@^++-- {{{ In-Between Function Application Combinator -----------------------------++-- | Prefix version of common pattern:+--+-- @+-- \\f -> a \`f\` b+-- @+--+-- Where @a@ and @b@ are fixed parameters. There is also infix version named+-- '~$~'. This function is defined as:+--+-- @+-- 'inbetween' a b f = (f $! a) $! b+-- @+--+-- Based on the above definition one can think of it as a variant function+-- application that deals with two arguments, where in example+-- 'Data.Function.$' only deals with one.+--+-- /Since version 0.11.0.0./+inbetween :: a -> b -> (a -> b -> r) -> r+inbetween a b f = (f $! a) $! b+infix 8 `inbetween`++-- | Infix version of common pattern:+--+-- @+-- \\f -> (f '$!' a) '$!' b+-- @+--+-- Where @a@ and @b@ are fixed parameters. There is also prefix version named+-- 'inbetween'.+--+-- /Since version 0.11.0.0./+(~$~) :: a -> b -> (a -> b -> r) -> r+(~$~) = inbetween+infix 8 ~$~++-- | Infix version of common pattern:+--+-- @+-- \\f -> (f '$!' a) '$!' b -- Notice the order of \'a\' and \'b\'.+-- @+--+-- /Since version 0.11.0.0./+(~$$~) :: b -> a -> (a -> b -> r) -> r+(b ~$$~ a) f = (f $! a) $! b+infix 8 ~$$~++-- | Construct a function that encodes idiom:+--+-- @+-- \\f -> f '$!' a '$!' b -- Notice the order of \'b\' and \'a\'.+-- @+--+-- Function 'inbetween' can be redefined in terms of 'withIn' as:+--+-- @+-- a \``inbetween`\` b = 'withIn' 'Data.Function.$' \\f -> a \`f\` b+-- @+--+-- On one hand you can think of this function as a specialized 'id' function+-- and on the other as a function application 'Data.Function.$'. All the+-- following definitions work for lazy variant:+--+-- @+-- 'withIn' f g = f g+-- 'withIn' = 'id'+-- 'withIn' = ('Data.Function.$')+-- @+--+-- For strict variant we use:+--+-- @+-- 'withIn' f g = f '$!' g+-- @+--+-- Usage examples:+--+-- @+-- newtype Foo a = Foo a+--+-- inFoo :: ((a -> Foo a) -> (Foo t -> t) -> r) -> r+-- inFoo = 'withIn' '$' \\f ->+-- Foo \`f\` \\(Foo a) -> Foo+-- @+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- inX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- inX = 'withIn' '$' \\f ->+-- (\\b s -> s{_x = b}) \`f\` _x+-- @+--+-- /Since version 0.11.0.0./+withIn :: ((a -> b -> r) -> r) -> (a -> b -> r) -> r+withIn f g = f $! g++-- | Construct a function that encodes idiom:+--+-- @+-- \\f -> b \`f\` a -- Notice the order of \'b\' and \'a\'.+-- @+--+-- Function '~$$~' can be redefined in terms of 'withReIn' as:+--+-- @+-- b '~$$~' a = 'withReIn' '$' \\f -> b \`f\` a+-- @+--+-- As 'withIn', but the function is flipped before applied. All of the+-- following definitions work for lazy variant:+--+-- @+-- 'withReIn' f g = f ('Data.Function.flip' g)+-- 'withReIn' = ('Data.Function..' 'Data.Function.flip')+-- @+--+-- For strict variant we can use:+--+-- @+-- 'withReIn' f g = f '$!' \\b a -> 'inbetween' a b g+-- 'withReIn' f g = f '$!' \\b a -> (a '~$~' b) g+-- 'withReIn' f g = f '$!' \\b a -> (b '~$$~' a) g+-- 'withReIn' f g = f '$!' \\b a -> g '$!' a '$!' b+-- 'withReIn' f g = 'withIn' f (\\b a -> g '$!' a '$!' b)+-- 'withReIn' f g = 'withIn' f $! 'flip' $! g -- With strict 'flip'.+-- @+--+-- Usage examples:+--+-- @+-- newtype Foo a = Foo a+--+-- inFoo :: ((a -> Foo a) -> (Foo t -> t) -> r) -> r+-- inFoo = 'withReIn' '$' \\f ->+-- (\\(Foo a) -> Foo) \`f\` Foo+-- @+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- inX :: ((Int -> Coords2D -> Coords2D) -> (Coords2D -> Int) -> r) -> r+-- inX = 'withReIn' '$' \\f ->+-- _x \`f\` \\b s -> s{_x = b}+-- @+--+-- /Since version 0.11.0.0./+withReIn :: ((b -> a -> r) -> r) -> (a -> b -> r) -> r+withReIn f g = withIn f $! flip $! g+{-# INLINE withReIn #-}++-- {{{ PreIso -----------------------------------------------------------------++-- | Construct a 'PreIso'; this function similar to /Iso/ constructor function+-- from /lens/ package:+--+-- @+-- iso :: (s -> a) -> (b -> t) -> Iso s t a b+-- @+--+-- Usage example:+--+-- @+-- data Foo a = Foo a+--+-- preFoo :: 'PreIso' r (Foo a) (Foo b) a b+-- preFoo = Foo \``preIso`\` \\(Foo a) -> a+-- @+preIso :: (s -> a) -> (b -> t) -> PreIso r s t a b+preIso = (~$$~)+{-# INLINE preIso #-}++-- | Flipped variant of 'preIso'.+--+-- Usage example:+--+-- @+-- data Foo a = Foo {_getFoo :: a}+--+-- preFoo :: 'PreIso' r (Foo a) (Foo b) a b+-- preFoo = _getFoo \``preIso'`\` Foo+-- @+preIso' :: (b -> t) -> (s -> a) -> PreIso r s t a b+preIso' = inbetween+{-# INLINE preIso' #-}++-- }}} PreIso -----------------------------------------------------------------+-- {{{ PreLens ----------------------------------------------------------------++-- | Construct a 'PreLens'; this function is similar to /Lens/ constructor+-- function from /lens/ package:+--+-- @+-- lens :: (s -> b -> t) -> (s -> a) -> Lens' s t a b+-- @+--+-- Usage example:+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- preX :: PreLens' r Coords2D Int+-- preX = (\\s b -> s{_x = b}) \``preLens`\` _x+-- @+preLens :: (s -> b -> t) -> (s -> a) -> PreLens r s t a b+preLens setter getter = (flip $! setter) ~$~ getter+{-# INLINE preLens #-}++-- | Flipped version of 'preLens' that takes getter first and setter second.+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- preX :: PreLens' r Coords2D Int+-- preX = _x \``preLens'`\` \\s b -> s{_x = b}+-- @+preLens' :: (s -> a) -> (s -> b -> t) -> PreLens r s t a b+preLens' = flip $! preLens+{-# INLINE preLens' #-}++-- | Construct a @Lens@ out of a 'PreLens'.+--+-- @+-- data Coords2D = Coords2D {_x :: Int, _y :: Int}+--+-- preX :: PreLens' r Coords2D Int+-- preX = _x \``preLens'`\` \\s b -> s{_x = b}+--+-- x :: Lens' Coords2D Int+-- x = 'le' preX+-- @+le :: Functor f+ => PreLens ((a -> f b) -> s -> f t) s t a b+ -> (a -> f b) -> s -> f t+le = ($! ((<^@~) . flip))+{-# INLINE le #-}++-- }}} PreLens ----------------------------------------------------------------+-- {{{ PrePrism ---------------------------------------------------------------++-- | Constract a 'PrePrism'; this function is similar to /Prism/ constructor+-- function from /lens/ package:+--+-- @+-- prism :: (b -> t) -> (s -> 'Either' t a) -> Prism s t a b+-- @+--+-- Usage example:+--+-- @+-- {-\# LANGUAGE LambdaCase \#-}+-- data Sum a b = A a | B b+--+-- preA :: 'PrePrism' r (Sum a c) (Sum b c) a b+-- preA = 'prePrism' A '$' \\case+-- A a -> 'Right' a+-- B b -> 'Left' (B b)+-- @+prePrism :: (b -> t) -> (s -> Either t a) -> PrePrism r s t a b+prePrism = inbetween+{-# INLINE prePrism #-}++-- | Simplified construction of 'PrePrism', which can be used in following+-- situations:+--+-- * Constructing /Prism/ for types isomorphic to 'Maybe' or+--+-- * when using 'Data.Typeable.cast' operation, or similar, which either+-- returns what you want or 'Data.Maybe.Nothing'.+--+-- Alternative type signature of this function is also:+--+-- @+-- 'prePrism'' :: 'PreIso' r s s ('Maybe' a) b -> 'PrePrism' r s s a b+-- @+prePrism' :: (b -> s) -> (s -> Maybe a) -> PrePrism r s s a b+prePrism' ana cata = ana ~$~ \s -> (maybe $! (Left $! s)) Right $! (cata $! s)+{-# INLINE prePrism' #-}++-- | Convert 'PreIso' in to 'PreLens' by injecting const to a setter function.+--+-- @+-- 'preIsoToPreLens' aPreIso f = aPreIso '$' \\fbt fsa -> 'const' fbt \`f\` fsa+-- @+preIsoToPreLens :: PreIso r s t a b -> PreLens r s t a b+-- :: (((b -> t) -> (s -> a) -> r) -> r)+-- -> ((b -> s -> t) -> (s -> a) -> r) -> r+preIsoToPreLens aPreIso f = aPreIso (\fbt fsa -> (const . fbt ~$~ fsa) $! f)+{-# INLINE preIsoToPreLens #-}++-- }}} PrePrism ---------------------------------------------------------------+-- }}} In-Between Function Application Combinator -----------------------------
+ src/Data/Function/Between/Strict/Internal.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module: $HEADER$+-- Description: Definitions used by family of strict function combinators.+-- Copyright: (c) 2013-2015, Peter Trško+-- License: BSD3+--+-- Maintainer: peter.trsko@gmail.com+-- Stability: experimental+-- Portability: NoImplicitPrelude+--+-- Definitions used by family of strict function combinators. These may come+-- handy, but clash with definitions available via "Prelude".+--+-- /Module available since version 0.11.0.0./+module Data.Function.Between.Strict.Internal+ ( (.)+ , flip+ )+ where++import Prelude (($!))+++-- | Strict variant of function composition. Defined as:+--+-- @+-- (f . g) x = f '$!' g '$!' x+-- @+--+-- /Internally used since version 0.10.0.0. Moved to/+-- /"Data.Function.Between.Strict.Internal" module and exposed in version/+-- /0.11.0.0./+(.) :: (b -> c) -> (a -> b) -> a -> c+(f . g) x = f $! g $! x+infixr 9 .+{-# INLINE (.) #-}++-- | Strict variant of 'Data.Function.flip'. Defined as:+--+-- @+-- 'flip' f b a = f '$!' a '$!' b+-- @+--+-- /Since version 0.11.0.0./+flip :: (a -> b -> c) -> b -> a -> c+flip f b a = (f $! a) $! b+{-# INLINE flip #-}
+ src/Data/Function/Between/Types.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module: $HEADER$+-- Description: Precursors to Iso, Lens and Prism types.+-- Copyright: (c) 2015, Peter Trško+-- License: BSD3+--+-- Maintainer: peter.trsko@gmail.com+-- Stability: experimental+-- Portability: NoImplicitPrelude+--+-- This module defines types that behave as a precursors to types defined in+-- <https://hackage.haskell.org/package/lens lens> library.+--+-- /Since version 0.11.0.0./+module Data.Function.Between.Types+ (+ -- * PreIso+ PreIso+ , PreIso'++ -- * PreLens+ , PreLens+ , PreLens'++ -- * PrePrism+ , PrePrism+ , PrePrism'+ )+ where++import Data.Either (Either)+++-- {{{ PreIso -----------------------------------------------------------------++-- | Family of types that can construct isomorphism between types.+--+-- /Since version 0.11.0.0./+type PreIso r s t a b = ((b -> t) -> (s -> a) -> r) -> r++-- | A simple 'PreIso'.+--+-- /Since version 0.11.0.0./+type PreIso' r s a = PreIso r s s a a++-- }}} PreIso -----------------------------------------------------------------++-- {{{ PreLens ----------------------------------------------------------------++-- | We can also view 'PreLens' as a special kind of 'PreIso':+--+-- @+-- 'PreLens' r s t a b = 'PreIso' r s (s -> t) a b+-- @+--+-- /Since version 0.11.0.0./+type PreLens r s t a b = ((b -> s -> t) -> (s -> a) -> r) -> r++-- | A simple 'PreLens', where we can not change the type of the information+-- we are focusing on. As a consequence neither the type of the container data+-- type can be changed.+--+-- /Since version 0.11.0.0./+type PreLens' r s a = PreLens r s s a a++-- }}} PreLens ----------------------------------------------------------------++-- {{{ PrePrism ---------------------------------------------------------------++-- | We can also get 'PrePrism' by specializing 'PreIso':+--+-- @+-- 'PrePrism' r s t a b = 'PreIso' r s t ('Either' t a) b+-- @+--+-- This fact is not surprising, since /Prisms/ are actually a special case of+-- isomorphism between two types.+--+-- Let's have a type @s@, and we want to extract specific information out of+-- it, but that information may not be there. Because of the fact that the type+-- @s@ can be a sum type. Imagine e.g. standard 'Maybe' data type:+--+-- @+-- 'Maybe' a = 'Data.Maybe.Nothing' | 'Data.Maybe.Just' a+-- @+--+-- How do we create something that can extrat that information from a sum type,+-- and if necessary, also reconstructs that sum type. The answer is /Prism/,+-- which is defined as an isomorphism between that type @s@ and @'Either' t a@+-- where @a@ is the information we want to extract and @t@ is the rest that we+-- don't care about.+--+-- You may have noticed, that definition of 'PrePrism' contains some type+-- variables that aren't mentioned in the above definition. The reason for this+-- is that, as with /Lenses/ we may want to extract value of type @a@, but when+-- constructing new data type we may want to change the type of that value in+-- to @b@ and therefore type @s@ may not fit, which is the reason why we have+-- type @t@ in there. Once again we can ilustrate this with 'Maybe'. Lets say+-- that we have a value of @s = 'Maybe' a@, but if we change the type of @a@ in+-- to @b@, and try to create 'Maybe' again, then it would have type @'Maybe' b+-- = t@.+--+-- /Since version 0.11.0.0./+type PrePrism r s t a b = ((b -> t) -> (s -> Either t a) -> r) -> r++-- | A simple 'PrePrism', where we can not change the type of the information+-- we are focusing on. As a consequence neither the type of the container data+-- type can be changed.+--+-- If we define 'PrePrism'' in terms of 'PreIso'' then we have even better+-- ilustration of /Prism/ concept in terms of isomorphism:+--+-- @+-- 'PrePrism'' r s a = 'PreIso'' r s ('Either' t a)+-- @+--+-- /Since version 0.11.0.0./+type PrePrism' r s a = PrePrism r s s a a++-- }}} PrePrism ---------------------------------------------------------------