linear-base-0.1.0: Standard library for linear types.
Safe HaskellSafe-Inferred
LanguageHaskell2010

Control.Optics.Linear

Description

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.

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 #-> f b

Note: We abbreviate Control for Control.Functor.Linear.

ProfunctorStrong (,) ()Strong Either VoidWandering
(->)XXX
(#->)XXX
(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

Documentation

newtype Optic_ arr s t a b Source #

Constructors

Optical ((a `arr` b) -> s `arr` t) 

type Optic c s t a b = forall arr. c arr => Optic_ arr s t a b Source #