content: -- | This module provides linear optics.
  --
  -- Documentation for specific optics (lenses, prisms, traversals and
  -- isomorphisms) are provided in their respective modules.
  --
  -- Here we just provide an overview.
  --
  -- Some familiarity with optics is needed to understand linear optics.
  -- Please go through the (hopefully friendly!) background material section
  -- if you are unfamiliar with lenses, prisms, traversals or isomorphisms.
  --
  -- == Background Material
  --
  -- If you don't know anything about optics, we suggest looking at the
  -- resources below and playing with the @lens@ package.
  --
  --  * [A great intro-to-lenses talk by Simon Peyton Jones](https://skillsmatter.com/skillscasts/4251-lenses-compositional-data-access-and-manipulation)
  --  * [A nice introductory blog post](https://tech.fpcomplete.com/haskell/tutorial/lens)
  --  * [A friendly introduction to prisms and isos](https://www.schoolofhaskell.com/school/to-infinity-and-beyond/pick-of-the-week/a-little-lens-starter-tutorial)
  --  * [The wiki of the @lens@ package](https://github.com/ekmett/lens/wiki)
  --  that contains some nice examples
  --
  -- == Conceptualizing and using optics
  --
  -- === What are /linear/ optics?
  --
  -- Optics can be conceptualized as a first class object with which you can
  -- view and map functions over sub-structure(s) within a larger structure.
  --
  -- __ /Linear/ optics are optics where the \"viewing\" and \"mapping\" are__
  -- __done with linear functions (and any corresponding structures hold values__
  -- __linearly, i.e., with constructors that use linear arrows).__
  --
  -- In types: a (linear) optic of type @Optic s t a b@ is a way of viewing the
  -- sub-structure(s) of type @a@ in the structure of type @s@ and mapping a
  -- function from an @a@ to a @b@ on those sub-structures in @s@ which change an
  -- @s@ to a @t@. The non-polymorphic version of the optic is specialized
  -- to the types @Optic s s a a@ and is usually defined with a tick mark,
  -- e.g., the non-polymorphic @Lens@ is @Lens'@.
  --
  -- There are four basic optics: traversals, lenses, prisms and isomorphisms.
  --
  -- === Sub-typing diagram of optics
  --
  -- \[ \texttt{Traversal} \]
  -- \[ \Huge \nearrow ~~~~~ \nwarrow \]
  -- \[ \texttt{Lens}\hspace{6em}\texttt{Prism} \]
  -- \[ \Huge \nwarrow ~~~~~ \nearrow \]
  -- \[ \texttt{Iso} \]
  --
  -- In the diagram above, the arrows @X --> Y@ mean any of the following
  -- equivalent things:
  --
  --  * X is a specialization of Y
  --  * X is a strict subset of Y
  --  * You can (basically) implement @f :: X -> Y@ with @f = id@
  --  but you can't implement @f :: Y -> X@.
  --
  -- === A bird's eye view of the types
  --
  -- The types of linear optics are generalizations of the standard optic
  -- types from the @lens@ package.
  --
  -- These are the standard optic types:
  --
  -- > type Traversal s t a b =
  -- >   forall f. Applicative f => (a -> f b) -> s -> f t
  -- > type Lens s t a b =
  -- >   forall f. Functor f => (a -> f b) -> (s -> f t)
  -- > type Prism s t a b =
  -- >   forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
  -- > type Iso s t a b =
  -- >   forall p f. (Profunctor p, Functor f) => a `p` (f b) -> s `p` (f t)
  --
  -- These are (basically) the linear optic types:
  --
  -- > type Traversal a b s t =
  -- >   forall arr.  Wandering arr => (a `arr` b) -> (s `arr` t)
  -- > type Lens a b s t =
  -- >   forall arr. Strong (,) () arr => (a `arr` b) -> (s `arr` t)
  -- > type Prism a b s t =
  -- >   forall arr. Strong Either Void arr => (a `arr` b) -> (s `arr` t)
  -- > type Iso a b s t =
  -- >   forall arr. Profunctor arr => (a `arr` b) -> (s `arr` t)
  --
  -- Below is a table that lists the instances of the typeclasses which
  -- generalize the standard optics.
  --
  -- Note that Kleisli arrows basically defined like so:
  --
  -- > type Kleisli f a b = a %1-> f b
  --
  -- /Note: We abbreviate Control for Control.Functor.Linear./
  --
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- |                 | Profunctor | Strong (,) () | Strong Either Void | Wandering |
  -- +=================+============+===============+====================+===========+
  -- |     @(->)@      |     X      |       X       |         X          |           |
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- |    @(%1->)@     |     X      |       X       |         X          |           |
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- |    (Prelude)    |            |               |                    |           |
  -- |  @Functor f@    |            |               |                    |           |
  -- | @=> Kleisli f@  |     X (4)  |       X       |                    |           |
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- | (Data.Functor)  |            |               |                    |           |
  -- |  @Functor f@    |            |               |                    |           |
  -- | @=> Kleisli f@  |     X      |               |                    |           |
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- |    (Prelude)    |            |               |                    |           |
  -- | @Applicative f@ |            |               |                    |           |
  -- | @=> Kleisli f@  |     X      |       X       |         X   (3)    |           |
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- |    (Control)    |            |               |                    |           |
  -- |   @Functor f@   |            |               |                    |           |
  -- | @=> Kleisli f@  |     X      |       X (2)   |                    |           |
  -- +-----------------+------------+---------------+--------------------+-----------+
  -- |    (Control)    |            |               |                    |           |
  -- | @Applicative f@ |            |               |                    |           |
  -- | @=> Kleisli f@  |     X      |       X       |         X          |     X (1) |
  -- +-----------------+------------+---------------+--------------------+-----------+
  --
  -- Essentially:
  --
  --  * The instance marked (1) implies that the linear traversal definition
  --    includes the standard one
  --  * The instance marked by (2) implies that the linear lens definition
  --    includes the standard one
  --  * The instance marked by (3) implies that the linear prism definition
  --    includes the standard one
  --  * The instance marked by (4) implies that the linear iso definition
  --    includes the standard one
  module Control.Optics.Linear
    ( Optic_ (..),
      Optic,
      module Control.Optics.Linear.Iso,
      module Control.Optics.Linear.Lens,
      module Control.Optics.Linear.Prism,
      module Control.Optics.Linear.Traversal,
    )
  where
  
  import Control.Optics.Linear.Internal (Optic, Optic_ (..))
  import Control.Optics.Linear.Iso
  import Control.Optics.Linear.Lens
  import Control.Optics.Linear.Prism
  import Control.Optics.Linear.Traversal
  