Skip to content

mroman42/vitrea

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vitrea

Pure profunctor lenses and optics via the profunctor representation theorem. You can read more about this representation in the following articles.

All the optics on this library are particular cases of a single unified definition. All the combinators on this library are instantiations of the profunctor optic to a particular Tambara module.

The usual notions of lawfulness (as in “Categories of optics”) apply to non-mixed optics (lenses, prisms, traversals…). However, there is not a consensus on what the natural notion of laws for a mixed optic should be, apart from specific cases like monadic lenses.

Examples

The library follows, where possible, the style of combinators of the lens library. Example code from “Profunctor optics: a categorical update” works directly under the library.

Example 1. (Lenses and prisms) The composition of a prism (address) and a lens (street) is used to parse a string and then access and modify one of its subfields.

let home = "221b Baker St, London, UK"
address :: Prism Address String
street :: Lens String Address

  >>> home?. address.street
  Just "221b Baker St"
  >>> home & address.street. ̃ "4 Marylebone Rd"
  "4 Marylebone Rd, London, UK"

Example 2. (Monadic lenses) A polymorphic family of type-changing monadic lenses for a logging monad is used to track each time a data holder (Box) is accessed.

box :: (Show b) => MonadicLens IO a b (Box a) (Box b)

  >>> return (Box 42)
        >>= mupdate box "hello"
        >>= mupdate box "world"
  [box]: contents changed to "hello".
  [box]: contents changed to "world".
  Box{"world"}

Example 3. (Algebraic lenses) A classifying lens (measure) is used both for accessing a the measurements of a point in the iris dataset and to classify new measurements into a species (Versicolor).

let iris =
[ Iris Setosa 4.9 3.0 1.4, 0.2
, Iris Setosa 4.7 3.2 1.3 0.2
, ...
, Iris Virginica 5.9 3.0 5.1 1.8 ]
measure :: AlgLens [] Measurements Flower

  >>> iris!!4 ˆ. measure
  (5.0, 3.6, 1.4, 0.2)
  >>> iris & measure .? Measurements (4.8, 3.2, 3.5, 2.1)
  Iris Versicolor (4.8, 3.1, 1.5, 0.1)

Example 4. (Traversals) The composition of a traversal (each) with a prism (address) and a lens (city) is used to parse a collection of strings and modify one of their subfields.

let mail =
[ "43 Adlington Rd, Wilmslow, United Kingdom"
, "26 Westcott Rd, Princeton, USA"
, "St James's Square, London, United Kingdom"
]
each :: Traversal String [String]
address :: Prism Address String
city :: Lens String Address

  >>> mail & each.address.city % ̃ uppercase
  [ "43 Adlington Rd, WILMSLOW, United Kingdom"
  , "26 Westcott Rd, PRINCETON, USA"
  , "St James's Square, LONDON, United Kingdom"
  ]

Example 5. (Kaleidoscopes) Following the previous Example 3, a kaleidoscope (aggregate) is composed with an algebraic lens to create a new point on the dataset by aggregating measurements with some function (mean, maximum) and then classifying it.

measure :: AlgebraicLens [] Measurements Flower
aggregate :: Kaleidoscope Float Measurements

  >>> iris & measure.aggregate >- mean
  Iris Versicolor; Sepal (5.843, 3.054); Petal (3.758, 1.198)

About

This is a complete rewriting from the first prototype of vitrea, maintained by @emilypi and @mroman42.

About

Optics via the profunctor representation theorem

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published