| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Optics.Iso
Description
An Isomorphism expresses the fact that two types have the
same structure, and hence can be converted from one to the other in
either direction.
Synopsis
- type Iso s t a b = Optic An_Iso NoIx s t a b
- type Iso' s a = Optic' An_Iso NoIx s a
- iso :: (s -> a) -> (b -> t) -> Iso s t a b
- equality :: (s ~ a, t ~ b) => Iso s t a b
- simple :: Iso' a a
- coerced :: (Coercible s a, Coercible t b) => Iso s t a b
- coercedTo :: forall a s. Coercible s a => Iso' s a
- coerced1 :: forall f s a. (Coercible s (f s), Coercible a (f a)) => Iso (f s) (f a) s a
- non :: Eq a => a -> Iso' (Maybe a) a
- non' :: Prism' a () -> Iso' (Maybe a) a
- anon :: a -> (a -> Bool) -> Iso' (Maybe a) a
- curried :: Iso ((a, b) -> c) ((d, e) -> f) (a -> b -> c) (d -> e -> f)
- uncurried :: Iso (a -> b -> c) (d -> e -> f) ((a, b) -> c) ((d, e) -> f)
- flipped :: Iso (a -> b -> c) (a' -> b' -> c') (b -> a -> c) (b' -> a' -> c')
- involuted :: (a -> a) -> Iso' a a
- class Bifunctor p => Swapped p where
- withIso :: Iso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
- au :: Functor f => Iso s t a b -> ((b -> t) -> f s) -> f a
- under :: Iso s t a b -> (t -> s) -> b -> a
- data An_Iso :: OpticKind
Formation
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 -> areview::Iso's a -> a -> s
over::Isos t a b -> (a -> b) -> s -> tset::Isos 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::Isos t a b -> s -> a
Computation
Well-formedness
The functions translating back and forth must be mutually inverse:
viewi .reviewi ≡idreviewi .viewi ≡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 equalityview equality :: a -> a
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 CharIdentity '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 is an isomorphism from non v to Maybe a'a.
non≡non'.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 01
>>>Map.fromList [] ^. at "hello" % non 00
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" .~ NothingfromList []
It can also be used in reverse to exclude a given value:
>>>non 0 # rem 10 4Just 2
>>>non 0 # rem 10 5Nothing
Since: 0.2
non' :: Prism' a () -> Iso' (Maybe a) a Source #
generalizes non' p to take any unit non (p # ())Prism
This function generates an isomorphism between
and Maybe (a | isn't p a)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" .~ NothingfromList []
Since: 0.2
anon :: a -> (a -> Bool) -> Iso' (Maybe a) a Source #
generalizes anon a p to take any value and a predicate.non a
anona ≡non'.nearlya
This function assumes that p a holds and generates an isomorphism
between True and Maybe (a | not (p a))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" .~ NothingfromList []
Since: 0.2
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)
Additional elimination forms
withIso :: Iso s t a b -> ((s -> a) -> (b -> t) -> r) -> r Source #
Extract the two components of an isomorphism.
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::Isos t a b ->Isob a t smapping:: (Functor f, Functor g) =>Isos t a b ->Iso(f s) (g t) (f a) (g b)
Subtyping
data An_Iso :: OpticKind Source #
Tag for an iso.
Instances
