Source code for haskpy.optics
"""Profunctor optics
.. currentmodule:: haskpy.optics
.. autosummary::
:toctree:
adapter
lens
prism
Resources:
- Profunctor Optics: Modular Data Accessors by Pickering, Gibbons, and Wu
- Profunctor Optics: The Categorical View by Bartosz Milewski
- https://github.com/cmk/profunctor-extras/tree/master/profunctor-optics
- https://github.com/hablapps/DontFearTheProfunctorOptics
- http://oleg.fi/gists/images/optics-hierarchy.svg
"""
from haskpy.functions import function, identity
[docs]@function
def adapter(receive, send):
"""(s -> a) -> (b -> t) -> AdapterP a b s t
where
type AdapterP a b s t = Profunctor p => p a b -> p s t
"""
def run(p):
"""(a -> b) -> s -> t, or more generally, AdapterP a b s t
Profunctor p => p a b -> p s t
"""
# For convenience, if we are given a plain Python function, let's wrap it
# with our function decorator to get all the Profunctor goodies
# automatically without the user needing to add the wrapping explicitly.
# Just a usability improvement.
if isinstance(p, type(lambda: 42)):
p = function(p)
return p.dimap(receive, send)
return run
[docs]@function
def lens(view, update):
"""(s -> a) -> ((b, s) -> t) -> LensP a b s t
where
type LensP a b s t = Cartesian p => p a b -> p s t
"""
@function
def run(p):
"""(a -> b) -> s -> t, or more generally, LensP a b s t
that is,
Cartesian p => p a b -> p s t
"""
# For convenience, if we are given a plain Python function, let's wrap it
# with our function decorator to get all the Profunctor goodies
# automatically without the user needing to add the wrapping explicitly.
# Just a usability improvement.
if isinstance(p, type(lambda: 42)):
p = function(p)
return p.first().dimap(lambda x: (view(x), x), update)
return run
[docs]@function
def prism(match, build):
"""(s -> Either t a) -> (b -> t) -> PrismP a b s t
where
type PrismP a b s t = Cocartesian p => p a b -> p s t
"""
# Just for easier user interface, wrap the given functions in case the user
# didn't do that
match = function(match)
build = function(build)
from haskpy.types.either import either
@function
def run(p):
"""(a -> b) -> s -> t, or more generally, PrismP a b s t
that is,
Cocartesian p => p a b -> p s t
"""
# For convenience, if we are given a plain Python function, let's wrap it
# with our function decorator to get all the Profunctor goodies
# automatically without the user needing to add the wrapping explicitly.
# Just a usability improvement.
if isinstance(p, type(lambda: 42)):
p = function(p)
return p.right().dimap(match, either(identity, build))
return run