diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -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
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2015, Peter Trško
+Copyright (c) 2013-2016, Peter Trško
 
 All rights reserved.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
 =======
 
 [![Hackage](http://img.shields.io/hackage/v/between.svg)][Hackage: between]
+[![Hackage Dependencies](https://img.shields.io/hackage-deps/v/between.svg)](http://packdeps.haskellers.com/reverse/between)
 [![Haskell Programming Language](https://img.shields.io/badge/language-Haskell-blue.svg)][Haskell.org]
 [![BSD3 License](http://img.shields.io/badge/license-BSD3-brightgreen.svg)][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."
diff --git a/between.cabal b/between.cabal
--- a/between.cabal
+++ b/between.cabal
@@ -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
diff --git a/src/Data/Function/Between.hs b/src/Data/Function/Between.hs
--- a/src/Data/Function/Between.hs
+++ b/src/Data/Function/Between.hs
@@ -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:
 --
 -- @
diff --git a/src/Data/Function/Between/Lazy.hs b/src/Data/Function/Between/Lazy.hs
--- a/src/Data/Function/Between/Lazy.hs
+++ b/src/Data/Function/Between/Lazy.hs
@@ -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 -----------------------------
diff --git a/src/Data/Function/Between/Strict.hs b/src/Data/Function/Between/Strict.hs
--- a/src/Data/Function/Between/Strict.hs
+++ b/src/Data/Function/Between/Strict.hs
@@ -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 -----------------------------
diff --git a/src/Data/Function/Between/Strict/Internal.hs b/src/Data/Function/Between/Strict/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Function/Between/Strict/Internal.hs
@@ -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 #-}
diff --git a/src/Data/Function/Between/Types.hs b/src/Data/Function/Between/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Function/Between/Types.hs
@@ -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 ---------------------------------------------------------------
