optics-core-0.4.1: Optics as an abstract interface: core definitions
Safe Haskell None
Language Haskell2010

Optics.Iso

Description

An Iso morphism expresses the fact that two types have the same structure, and hence can be converted from one to the other in either direction.

Synopsis

Formation

type Iso s t a b = Optic An_Iso NoIx s t a b Source #

Type synonym for a type-modifying iso.

type Iso' s a = Optic' An_Iso NoIx s a Source #

Type synonym for a type-preserving iso.

Introduction

iso :: (s -> a) -> (b -> t) -> Iso s t a b Source #

Build an iso from a pair of inverse functions.

If you want to build an Iso from the van Laarhoven representation, use isoVL from the optics-vl package.

Elimination

An Iso is in particular a Getter , a Review and a Setter , therefore you can specialise types to obtain:

view   :: Iso' s a -> s -> a
review :: Iso' s a -> a -> s
over   :: Iso s t a b -> (a -> b) -> s -> t
set    :: Iso s t a b ->       b  -> s -> t

If you want to view a type-modifying Iso that is insufficiently polymorphic to be used as a type-preserving Iso' , use getting :

view . getting :: Iso s t a b -> s -> a

Computation

view   (iso f g) ≡ f
review (iso f g) ≡ g

Well-formedness

The functions translating back and forth must be mutually inverse:

view i . review i ≡ id
review i . view i ≡ id

Additional introduction forms

equality :: (s ~ a, t ~ b) => Iso s t a b Source #

Capture type constraints as an isomorphism.

Note: This is the identity optic:

>>> :t view equality
view equality :: a -> a

simple :: Iso' a a Source #

Proof of reflexivity.

coerced :: ( Coercible s a, Coercible t b) => Iso s t a b Source #

Data types that are representationally equal are isomorphic.

>>> view coerced 'x' :: Identity Char
Identity 'x'

coercedTo :: forall a s. Coercible s a => Iso' s a Source #

Type-preserving version of coerced with type parameters rearranged for TypeApplications.

>>> newtype MkInt = MkInt Int deriving Show
>>> over (coercedTo @Int) (*3) (MkInt 2)
MkInt 6

coerced1 :: forall f s a. ( Coercible s (f s), Coercible a (f a)) => Iso (f s) (f a) s a Source #

Special case of coerced for trivial newtype wrappers.

>>> over (coerced1 @Identity) (++ "bar") (Identity "foo")
Identity "foobar"

non :: Eq a => a -> Iso' ( Maybe a) a Source #

If v is an element of a type a , and a' is a sans the element v , then non v is an isomorphism from Maybe a' to a .

nonnon' . only

Keep in mind this is only a real isomorphism if you treat the domain as being Maybe (a sans v) .

This is practically quite useful when you want to have a Map where all the entries should have non-zero values.

>>> Map.fromList [("hello",1)] & at "hello" % non 0 %~ (+2)
fromList [("hello",3)]
>>> Map.fromList [("hello",1)] & at "hello" % non 0 %~ (subtract 1)
fromList []
>>> Map.fromList [("hello",1)] ^. at "hello" % non 0
1
>>> Map.fromList [] ^. at "hello" % non 0
0

This combinator is also particularly useful when working with nested maps.

e.g. When you want to create the nested Map when it is missing:

>>> Map.empty & at "hello" % non Map.empty % at "world" ?~ "!!!"
fromList [("hello",fromList [("world","!!!")])]

and when have deleting the last entry from the nested Map mean that we should delete its entry from the surrounding one:

>>> Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non Map.empty % at "world" .~ Nothing
fromList []

It can also be used in reverse to exclude a given value:

>>> non 0 # rem 10 4
Just 2
>>> non 0 # rem 10 5
Nothing

Since: 0.2

non' :: Prism' a () -> Iso' ( Maybe a) a Source #

non' p generalizes non (p # ()) to take any unit Prism

This function generates an isomorphism between Maybe (a | isn't p a) and a .

>>> Map.singleton "hello" Map.empty & at "hello" % non' _Empty % at "world" ?~ "!!!"
fromList [("hello",fromList [("world","!!!")])]
>>> Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non' _Empty % at "world" .~ Nothing
fromList []

Since: 0.2

anon :: a -> (a -> Bool ) -> Iso' ( Maybe a) a Source #

anon a p generalizes non a to take any value and a predicate.

anon a ≡ non' . nearly a

This function assumes that p a holds True and generates an isomorphism between Maybe (a | not (p a)) and a .

>>> Map.empty & at "hello" % anon Map.empty Map.null % at "world" ?~ "!!!"
fromList [("hello",fromList [("world","!!!")])]
>>> Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % anon Map.empty Map.null % at "world" .~ Nothing
fromList []

Since: 0.2

curried :: Iso ((a, b) -> c) ((d, e) -> f) (a -> b -> c) (d -> e -> f) Source #

The canonical isomorphism for currying and uncurrying a function.

curried = iso curry uncurry
>>> view curried fst 3 4
3

uncurried :: Iso (a -> b -> c) (d -> e -> f) ((a, b) -> c) ((d, e) -> f) Source #

The canonical isomorphism for uncurrying and currying a function.

uncurried = iso uncurry curry
uncurried = re curried
>>> (view uncurried (+)) (1,2)
3

flipped :: Iso (a -> b -> c) (a' -> b' -> c') (b -> a -> c) (b' -> a' -> c') Source #

The isomorphism for flipping a function.

>>> (view flipped (,)) 1 2
(2,1)

involuted :: (a -> a) -> Iso' a a Source #

Given a function that is its own inverse, this gives you an Iso using it in both directions.

involutedjoin iso
>>> "live" ^. involuted reverse
"evil"
>>> "live" & involuted reverse %~ ('d':)
"lived"

class Bifunctor p => Swapped p where Source #

This class provides for symmetric bifunctors.

Methods

swapped :: Iso (p a b) (p c d) (p b a) (p d c) Source #

swapped . swappedid
first f . swapped = swapped . second f
second g . swapped = swapped . first g
bimap f g . swapped = swapped . bimap g f
>>> view swapped (1,2)
(2,1)

Instances

Instances details
Swapped Either Source #
Instance details

Defined in Optics.Iso

Swapped (,) Source #
Instance details

Defined in Optics.Iso

Methods

swapped :: Iso (a, b) (c, d) (b, a) (d, c) Source #

Additional elimination forms

withIso :: Iso s t a b -> ((s -> a) -> (b -> t) -> r) -> r Source #

Extract the two components of an isomorphism.

au :: Functor f => Iso s t a b -> ((b -> t) -> f s) -> f a Source #

Based on ala from Conor McBride's work on Epigram.

This version is generalized to accept any Iso , not just a newtype .

>>> au (coerced1 @Sum) foldMap [1,2,3,4]
10

You may want to think of this combinator as having the following, simpler type:

au :: Iso s t a b -> ((b -> t) -> e -> s) -> e -> a

under :: Iso s t a b -> (t -> s) -> b -> a Source #

The opposite of working over a Setter is working under an isomorphism.

underover . re

Combinators

The re combinator can be used to reverse an Iso , and the mapping combinator to lift an Iso to an Iso on functorial values.

re      ::                           Iso s t a b -> Iso b a t s
mapping :: (Functor f, Functor g) => Iso s t a b -> Iso (f s) (g t) (f a) (g b)

Subtyping

data An_Iso :: OpticKind Source #

Tag for an iso.

Instances

Instances details
ReversibleOptic An_Iso Source #
Instance details

Defined in Optics.Re

Associated Types

type ReversedOptic An_Iso = (r :: Type ) Source #

Methods

re :: forall (is :: IxList ) s t a b. AcceptsEmptyIndices "re" is => Optic An_Iso is s t a b -> Optic ( ReversedOptic An_Iso ) is b a t s Source #

Is An_Iso A_Review Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_ReversedLens Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_Fold Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso An_AffineFold Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_Getter Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_ReversedPrism Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_Setter Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_Traversal Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso An_AffineTraversal Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_Prism Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Is An_Iso A_Lens Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

Arrow arr => ArrowOptic An_Iso arr Source #
Instance details

Defined in Optics.Arrow

Methods

overA :: forall (is :: IxList ) s t a b. Optic An_Iso is s t a b -> arr a b -> arr s t Source #

k ~ A_Review => JoinKinds A_Review An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_ReversedLens => JoinKinds A_ReversedLens An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Fold => JoinKinds A_Fold An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ An_AffineFold => JoinKinds An_AffineFold An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Getter => JoinKinds A_Getter An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_ReversedPrism => JoinKinds A_ReversedPrism An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Setter => JoinKinds A_Setter An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Traversal => JoinKinds A_Traversal An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ An_AffineTraversal => JoinKinds An_AffineTraversal An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Prism => JoinKinds A_Prism An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Lens => JoinKinds A_Lens An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Review => JoinKinds An_Iso A_Review k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_ReversedLens => JoinKinds An_Iso A_ReversedLens k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Fold => JoinKinds An_Iso A_Fold k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ An_AffineFold => JoinKinds An_Iso An_AffineFold k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Getter => JoinKinds An_Iso A_Getter k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_ReversedPrism => JoinKinds An_Iso A_ReversedPrism k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Setter => JoinKinds An_Iso A_Setter k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Traversal => JoinKinds An_Iso A_Traversal k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ An_AffineTraversal => JoinKinds An_Iso An_AffineTraversal k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Prism => JoinKinds An_Iso A_Prism k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ A_Lens => JoinKinds An_Iso A_Lens k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

k ~ An_Iso => JoinKinds An_Iso An_Iso k Source #
Instance details

Defined in Optics.Internal.Optic.Subtyping

ToReadOnly An_Iso s t a b Source #
Instance details

Defined in Optics.ReadOnly

( Functor f, Functor g) => MappingOptic An_Iso f g s t a b Source #
Instance details

Defined in Optics.Mapping

Methods

mapping :: forall (is :: IxList ). AcceptsEmptyIndices "mapping" is => Optic An_Iso is s t a b -> Optic ( MappedOptic An_Iso ) is (f s) (g t) (f a) (g b) Source #

type ReversedOptic An_Iso Source #
Instance details

Defined in Optics.Re

type ReadOnlyOptic An_Iso Source #
Instance details

Defined in Optics.ReadOnly

type MappedOptic An_Iso Source #
Instance details

Defined in Optics.Mapping