-- | 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