HORIZON HASKELLDocslts/ghc-10.0.x77a86622026-10-31Search packagesCtrl K
Theme: |

GHC 10.0.0.20260917 · lts/ghc-10.0.x · 77a8662 · 2026-10-31

Moduleoptics-core-0.4.2Haskell2010

Optics.Iso

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.

Contents
  1. Formation
  2. Introduction
  3. Elimination
  4. Computation
  5. Well-formedness
  6. Additional introduction forms
  7. Additional elimination forms
  8. Combinators
  9. Subtyping
Synopsis

Formation

Introduction

valueiso :: (s -> a) -> (b -> t) -> Iso s t a b

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

valueequality :: (s ~ a, t ~ b) => Iso s t a b

Capture type constraints as an isomorphism.

Note: This is the identity optic:

Example1 expression
:t view equalityview equality :: a -> a
valuecoerced :: (Coercible s a, Coercible t b) => Iso s t a b

Data types that are representationally equal are isomorphic.

Example1 expression
view coerced 'x' :: Identity CharIdentity 'x'
valuecoercedTo :: Coercible s a => Iso' s a

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

Example1 expression
newtype MkInt = MkInt Int deriving Show
Example1 expression
over (coercedTo @Int) (*3) (MkInt 2)MkInt 6
valuecoerced1 :: (Coercible s (f s), Coercible a (f a)) => Iso (f s) (f a) s a

Special case of coerced for trivial newtype wrappers.

Example1 expression
over (coerced1 @Identity) (++ "bar") (Identity "foo")Identity "foobar"
valuenon :: Eq a => a -> Iso' (Maybe a) a

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.

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 Data.Map.Map where all the entries should have non-zero values.

Example1 expression
Map.fromList [("hello",1)] & at "hello" % non 0 %~ (+2)fromList [("hello",3)]
Example1 expression
Map.fromList [("hello",1)] & at "hello" % non 0 %~ (subtract 1)fromList []
Example1 expression
Map.fromList [("hello",1)] ^. at "hello" % non 01
Example1 expression
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 Data.Map.Map when it is missing:

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

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

Example1 expression
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:

Example1 expression
non 0 # rem 10 4Just 2
Example1 expression
non 0 # rem 10 5Nothing
valuenon' :: Prism' a () -> Iso' (Maybe a) a

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

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

Example1 expression
Map.singleton "hello" Map.empty & at "hello" % non' _Empty % at "world" ?~ "!!!"fromList [("hello",fromList [("world","!!!")])]
Example1 expression
Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non' _Empty % at "world" .~ NothingfromList []
valueanon :: a -> (a -> Bool) -> Iso' (Maybe a) a

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.

Example1 expression
Map.empty & at "hello" % anon Map.empty Map.null % at "world" ?~ "!!!"fromList [("hello",fromList [("world","!!!")])]
Example1 expression
Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % anon Map.empty Map.null % at "world" .~ NothingfromList []
valuecurried :: Iso ((a, b) -> c) ((d, e) -> f) (a -> b -> c) (d -> e -> f)

The canonical isomorphism for currying and uncurrying a function.

curried = iso curry uncurry
Example1 expression
view curried fst 3 43
valueflipped :: Iso (a -> b -> c) (a' -> b' -> c') (b -> a -> c) (b' -> a' -> c')

The isomorphism for flipping a function.

Example1 expression
(view flipped (,)) 1 2(2,1)
valueinvoluted :: (a -> a) -> Iso' a a

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

involuted ≡ join iso
Example1 expression
"live" ^. involuted reverse"evil"
Example1 expression
"live" & involuted reverse %~ ('d':)"lived"

Additional elimination forms

valuewithIso :: Iso s t a b -> ((s -> a) -> (b -> t) -> r) -> r

Extract the two components of an isomorphism.

valueau :: Functor f => Iso s t a b -> ((b -> t) -> f s) -> f a

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

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

Example1 expression
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

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

datadata An_Iso

Tag for an iso.

Instances41ReversibleOptic, Is, ArrowOptic, JoinKinds, ToReadOnly, MappingOptic, …