linear-base-0.2.0: src/Control/Optics/Linear.hs
-- | 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