Add documentation for indexed optics, etc.
This commit is contained in:
parent
07b3028eda
commit
53df8dfced
|
@ -9,8 +9,12 @@ import Control.Lens.Setter
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
||| An interface that provides an `Optional` to access a given index in a
|
||||||
|
||| container, such as an ordinal position in a `List` or `Vect` or a key in a
|
||||||
|
||| map.
|
||||||
public export
|
public export
|
||||||
interface Ixed i v a | a where
|
interface Ixed i v a | a where
|
||||||
|
||| An optional that possibly accesses a value at a given index of a container.
|
||||||
ix : i -> Optional' a v
|
ix : i -> Optional' a v
|
||||||
|
|
||||||
public export
|
public export
|
||||||
|
@ -18,8 +22,14 @@ public export
|
||||||
ix k = optional' (Just . ($ k)) (\f,x,k' => if k == k' then x else f k')
|
ix k = optional' (Just . ($ k)) (\f,x,k' => if k == k' then x else f k')
|
||||||
|
|
||||||
|
|
||||||
|
||| An interface that provides a lens to access a given index in a collection.
|
||||||
|
||| This is different from `Ixed` in that the lens cannot fail to get a value.
|
||||||
|
|||
|
||||||
|
||| Implementations of this interface may use different index types for `ix` and
|
||||||
|
||| `ix'`; for example, `Vect n a` uses `Nat` for `ix` and `Fin n` for `ix'`.
|
||||||
public export
|
public export
|
||||||
interface Ixed i v a => Ixed' i i' v a | a where
|
interface Ixed i v a => Ixed' i i' v a | a where
|
||||||
|
||| An lens that infallibly accesses a value at a given index of a container.
|
||||||
ix' : i' -> Lens' a v
|
ix' : i' -> Lens' a v
|
||||||
|
|
||||||
public export
|
public export
|
||||||
|
@ -27,10 +37,27 @@ public export
|
||||||
ix' k = lens ($ k) (\f,x,k' => if k == k' then x else f k')
|
ix' k = lens ($ k) (\f,x,k' => if k == k' then x else f k')
|
||||||
|
|
||||||
|
|
||||||
|
||| This interface provides a lens to read, write, add or delete the value
|
||||||
|
||| associated to a key in a map or map-like container.
|
||||||
|
|||
|
||||||
|
||| This lens must follow the law:
|
||||||
|
||| * `ix == at . Just_`
|
||||||
|
|||
|
||||||
|
||| If you do not need to add or delete keys, `ix` is more convenient.
|
||||||
public export
|
public export
|
||||||
interface Ixed i v a => At i v a | a where
|
interface Ixed i v a => At i v a | a where
|
||||||
|
||| A lens that can be used to read, write, add or delete a value associated
|
||||||
|
||| with a key in a map-like container.
|
||||||
|
|||
|
||||||
|
||| If you do not need to add or delete keys, `ix` is more convenient.
|
||||||
at : i -> Lens' a (Maybe v)
|
at : i -> Lens' a (Maybe v)
|
||||||
|
|
||||||
|
||| Delete the value at a particular key in a container using `At`.
|
||||||
public export
|
public export
|
||||||
sans : At i v a => i -> a -> a
|
sans : At i v a => i -> a -> a
|
||||||
sans k = at k .~ Nothing
|
sans k = at k .~ Nothing
|
||||||
|
|
||||||
|
||| Add a value at a particular key in a container using `At`.
|
||||||
|
public export
|
||||||
|
add : At i v a => i -> v -> a -> a
|
||||||
|
add k = (at k ?~)
|
||||||
|
|
|
@ -42,6 +42,7 @@ public export
|
||||||
0 Fold : (s,a : Type) -> Type
|
0 Fold : (s,a : Type) -> Type
|
||||||
Fold = Simple (Optic IsFold)
|
Fold = Simple (Optic IsFold)
|
||||||
|
|
||||||
|
||| An indexed fold returns indices while getting.
|
||||||
public export
|
public export
|
||||||
0 IndexedFold : (i,s,a : Type) -> Type
|
0 IndexedFold : (i,s,a : Type) -> Type
|
||||||
IndexedFold = Simple . IndexedOptic IsFold
|
IndexedFold = Simple . IndexedOptic IsFold
|
||||||
|
@ -73,6 +74,7 @@ public export
|
||||||
folding : Foldable f => (s -> f a) -> Fold s a
|
folding : Foldable f => (s -> f a) -> Fold s a
|
||||||
folding @{_} f @{MkIsFold _} = rphantom . contramapFst f . wander traverse_
|
folding @{_} f @{MkIsFold _} = rphantom . contramapFst f . wander traverse_
|
||||||
|
|
||||||
|
||| Construct an indexed fold from a function into a foldable container.
|
||||||
public export
|
public export
|
||||||
ifolding : Foldable f => (s -> f (i, a)) -> IndexedFold i s a
|
ifolding : Foldable f => (s -> f (i, a)) -> IndexedFold i s a
|
||||||
ifolding @{_} f @{MkIsFold _} @{ind} =
|
ifolding @{_} f @{MkIsFold _} @{ind} =
|
||||||
|
@ -109,6 +111,8 @@ public export
|
||||||
foldMapOf : Monoid m => Fold s a -> (a -> m) -> s -> m
|
foldMapOf : Monoid m => Fold s a -> (a -> m) -> s -> m
|
||||||
foldMapOf l = runForget . l . MkForget
|
foldMapOf l = runForget . l . MkForget
|
||||||
|
|
||||||
|
||| Map each focus of an optic to a monoid value with access to the index and
|
||||||
|
||| combine them.
|
||||||
public export
|
public export
|
||||||
ifoldMapOf : Monoid m => IndexedFold i s a -> (i -> a -> m) -> s -> m
|
ifoldMapOf : Monoid m => IndexedFold i s a -> (i -> a -> m) -> s -> m
|
||||||
ifoldMapOf l = runForget . l @{%search} @{Idxed} . MkForget . uncurry
|
ifoldMapOf l = runForget . l @{%search} @{Idxed} . MkForget . uncurry
|
||||||
|
@ -119,6 +123,8 @@ public export
|
||||||
foldrOf : Fold s a -> (a -> acc -> acc) -> acc -> s -> acc
|
foldrOf : Fold s a -> (a -> acc -> acc) -> acc -> s -> acc
|
||||||
foldrOf l = flip . foldMapOf @{MkMonoid @{MkSemigroup (.)} id} l
|
foldrOf l = flip . foldMapOf @{MkMonoid @{MkSemigroup (.)} id} l
|
||||||
|
|
||||||
|
||| Combine the focuses of an optic using the provided function with access to
|
||||||
|
||| the index, starting from the right.
|
||||||
public export
|
public export
|
||||||
ifoldrOf : IndexedFold i s a -> (i -> a -> acc -> acc) -> acc -> s -> acc
|
ifoldrOf : IndexedFold i s a -> (i -> a -> acc -> acc) -> acc -> s -> acc
|
||||||
ifoldrOf l = flip . ifoldMapOf @{MkMonoid @{MkSemigroup (.)} id} l
|
ifoldrOf l = flip . ifoldMapOf @{MkMonoid @{MkSemigroup (.)} id} l
|
||||||
|
@ -129,6 +135,8 @@ public export
|
||||||
foldlOf : Fold s a -> (acc -> a -> acc) -> acc -> s -> acc
|
foldlOf : Fold s a -> (acc -> a -> acc) -> acc -> s -> acc
|
||||||
foldlOf l = flip . foldMapOf @{MkMonoid @{MkSemigroup $ flip (.)} id} l . flip
|
foldlOf l = flip . foldMapOf @{MkMonoid @{MkSemigroup $ flip (.)} id} l . flip
|
||||||
|
|
||||||
|
||| Combine the focuses of an optic using the provided function with access to
|
||||||
|
||| the index, starting from the left.
|
||||||
public export
|
public export
|
||||||
ifoldlOf : IndexedFold i s a -> (i -> acc -> a -> acc) -> acc -> s -> acc
|
ifoldlOf : IndexedFold i s a -> (i -> acc -> a -> acc) -> acc -> s -> acc
|
||||||
ifoldlOf l = flip . ifoldMapOf @{MkMonoid @{MkSemigroup $ flip (.)} id} l . (flip .)
|
ifoldlOf l = flip . ifoldMapOf @{MkMonoid @{MkSemigroup $ flip (.)} id} l . (flip .)
|
||||||
|
@ -158,6 +166,8 @@ traverseOf_ l f =
|
||||||
let _ = MkMonoid @{MkSemigroup (*>)} (pure ())
|
let _ = MkMonoid @{MkSemigroup (*>)} (pure ())
|
||||||
in foldMapOf l (ignore . f)
|
in foldMapOf l (ignore . f)
|
||||||
|
|
||||||
|
||| Map each focus of an optic to a computation with access to the index,
|
||||||
|
||| evaluate those computations and discard the results.
|
||||||
public export
|
public export
|
||||||
itraverseOf_ : Applicative f => IndexedFold i s a -> (i -> a -> f b) -> s -> f ()
|
itraverseOf_ : Applicative f => IndexedFold i s a -> (i -> a -> f b) -> s -> f ()
|
||||||
itraverseOf_ l f =
|
itraverseOf_ l f =
|
||||||
|
@ -169,6 +179,7 @@ public export
|
||||||
forOf_ : Applicative f => Fold s a -> s -> (a -> f b) -> f ()
|
forOf_ : Applicative f => Fold s a -> s -> (a -> f b) -> f ()
|
||||||
forOf_ = flip . traverseOf_
|
forOf_ = flip . traverseOf_
|
||||||
|
|
||||||
|
||| A version of `itraverseOf_` with the arguments flipped.
|
||||||
public export
|
public export
|
||||||
iforOf_ : Applicative f => IndexedFold i s a -> s -> (i -> a -> f b) -> f ()
|
iforOf_ : Applicative f => IndexedFold i s a -> s -> (i -> a -> f b) -> f ()
|
||||||
iforOf_ = flip . itraverseOf_
|
iforOf_ = flip . itraverseOf_
|
||||||
|
@ -188,11 +199,21 @@ public export
|
||||||
allOf : Fold s a -> (a -> Bool) -> s -> Bool
|
allOf : Fold s a -> (a -> Bool) -> s -> Bool
|
||||||
allOf = foldMapOf @{All}
|
allOf = foldMapOf @{All}
|
||||||
|
|
||||||
|
||| Return `True` if all focuses of the indexed optic satisfy the predicate.
|
||||||
|
public export
|
||||||
|
iallOf : IndexedFold i s a -> (i -> a -> Bool) -> s -> Bool
|
||||||
|
iallOf = ifoldMapOf @{All}
|
||||||
|
|
||||||
||| Return `True` if any focuses of the optic satisfy the predicate.
|
||| Return `True` if any focuses of the optic satisfy the predicate.
|
||||||
public export
|
public export
|
||||||
anyOf : Fold s a -> (a -> Bool) -> s -> Bool
|
anyOf : Fold s a -> (a -> Bool) -> s -> Bool
|
||||||
anyOf = foldMapOf @{Any}
|
anyOf = foldMapOf @{Any}
|
||||||
|
|
||||||
|
||| Return `True` if any focuses of the indexed optic satisfy the predicate.
|
||||||
|
public export
|
||||||
|
ianyOf : IndexedFold i s a -> (i -> a -> Bool) -> s -> Bool
|
||||||
|
ianyOf = ifoldMapOf @{Any}
|
||||||
|
|
||||||
|
|
||||||
||| Return `True` if the element occurs in the focuses of the optic.
|
||| Return `True` if the element occurs in the focuses of the optic.
|
||||||
public export
|
public export
|
||||||
|
@ -212,6 +233,10 @@ public export
|
||||||
firstOf : Fold s a -> s -> Maybe a
|
firstOf : Fold s a -> s -> Maybe a
|
||||||
firstOf l = foldMapOf l Just
|
firstOf l = foldMapOf l Just
|
||||||
|
|
||||||
|
||| Access the first focus value and index of an indexed optic, returning Nothing
|
||||||
|
||| if there are no focuses.
|
||||||
|
|||
|
||||||
|
||| This is identical to `ipreview`.
|
||||||
public export
|
public export
|
||||||
ifirstOf : IndexedFold i s a -> s -> Maybe (i, a)
|
ifirstOf : IndexedFold i s a -> s -> Maybe (i, a)
|
||||||
ifirstOf l = runForget $ l @{%search} @{Idxed} $ MkForget Just
|
ifirstOf l = runForget $ l @{%search} @{Idxed} $ MkForget Just
|
||||||
|
@ -222,6 +247,8 @@ public export
|
||||||
lastOf : Fold s a -> s -> Maybe a
|
lastOf : Fold s a -> s -> Maybe a
|
||||||
lastOf l = foldMapOf @{MkMonoid @{MkSemigroup $ flip (<+>)} neutral} l Just
|
lastOf l = foldMapOf @{MkMonoid @{MkSemigroup $ flip (<+>)} neutral} l Just
|
||||||
|
|
||||||
|
||| Access the last focus value and index of an indexed optic, returning Nothing
|
||||||
|
||| if there are no focuses.
|
||||||
public export
|
public export
|
||||||
ilastOf : IndexedFold i s a -> s -> Maybe (i, a)
|
ilastOf : IndexedFold i s a -> s -> Maybe (i, a)
|
||||||
ilastOf l =
|
ilastOf l =
|
||||||
|
@ -271,12 +298,20 @@ public export
|
||||||
(^?) x l = preview l x
|
(^?) x l = preview l x
|
||||||
|
|
||||||
|
|
||||||
|
||| Access the first focus value and index of an indexed optic, returning Nothing
|
||||||
|
||| if there are no focuses.
|
||||||
|
|||
|
||||||
|
||| This is an alias for `ifirstOf`.
|
||||||
public export
|
public export
|
||||||
ipreview : IndexedFold i s a -> s -> Maybe (i, a)
|
ipreview : IndexedFold i s a -> s -> Maybe (i, a)
|
||||||
ipreview = ifirstOf
|
ipreview = ifirstOf
|
||||||
|
|
||||||
infixl 8 ^@?
|
infixl 8 ^@?
|
||||||
|
|
||||||
|
||| Access the first focus value and index of an indexed optic, returning Nothing
|
||||||
|
||| if there are no focuses.
|
||||||
|
|||
|
||||||
|
||| This is the operator form of `ipreview`.
|
||||||
public export
|
public export
|
||||||
(^@?) : s -> IndexedFold i s a -> Maybe (i, a)
|
(^@?) : s -> IndexedFold i s a -> Maybe (i, a)
|
||||||
(^@?) x l = ipreview l x
|
(^@?) x l = ipreview l x
|
||||||
|
@ -289,6 +324,10 @@ public export
|
||||||
pre : Fold s a -> OptionalFold s a
|
pre : Fold s a -> OptionalFold s a
|
||||||
pre = folding . preview
|
pre = folding . preview
|
||||||
|
|
||||||
|
||| Convert an `IndexedFold` into an `IndexedOptionalFold` that accesses the
|
||||||
|
||| first focus element.
|
||||||
|
|||
|
||||||
|
||| For the traversal version of this, see `isingular`.
|
||||||
public export
|
public export
|
||||||
ipre : IndexedFold i s a -> IndexedOptionalFold i s a
|
ipre : IndexedFold i s a -> IndexedOptionalFold i s a
|
||||||
ipre = ifolding . ipreview
|
ipre = ifolding . ipreview
|
||||||
|
@ -309,12 +348,16 @@ public export
|
||||||
(^..) s l = toListOf l s
|
(^..) s l = toListOf l s
|
||||||
|
|
||||||
|
|
||||||
|
||| Return a list of all focuses and indices of an indexed fold.
|
||||||
public export
|
public export
|
||||||
itoListOf : IndexedFold i s a -> s -> List (i, a)
|
itoListOf : IndexedFold i s a -> s -> List (i, a)
|
||||||
itoListOf l = ifoldrOf l ((::) .: (,)) []
|
itoListOf l = ifoldrOf l ((::) .: (,)) []
|
||||||
|
|
||||||
infixl 8 ^@..
|
infixl 8 ^@..
|
||||||
|
|
||||||
|
||| Return a list of all focuses and indices of an indexed fold.
|
||||||
|
|||
|
||||||
|
||| This is the operator form of `itoListOf`.
|
||||||
public export
|
public export
|
||||||
(^@..) : s -> IndexedFold i s a -> List (i, a)
|
(^@..) : s -> IndexedFold i s a -> List (i, a)
|
||||||
(^@..) x l = itoListOf l x
|
(^@..) x l = itoListOf l x
|
||||||
|
|
|
@ -36,6 +36,7 @@ public export
|
||||||
0 Getter : (s,a : Type) -> Type
|
0 Getter : (s,a : Type) -> Type
|
||||||
Getter = Simple (Optic IsGetter)
|
Getter = Simple (Optic IsGetter)
|
||||||
|
|
||||||
|
||| An indexed getter returns an index while getting.
|
||||||
public export
|
public export
|
||||||
0 IndexedGetter : (i,s,a : Type) -> Type
|
0 IndexedGetter : (i,s,a : Type) -> Type
|
||||||
IndexedGetter = Simple . IndexedOptic IsGetter
|
IndexedGetter = Simple . IndexedOptic IsGetter
|
||||||
|
@ -51,6 +52,7 @@ public export
|
||||||
to : (s -> a) -> Getter s a
|
to : (s -> a) -> Getter s a
|
||||||
to f @{MkIsGetter _} = lmap f . rphantom
|
to f @{MkIsGetter _} = lmap f . rphantom
|
||||||
|
|
||||||
|
||| Construct an indexed getter from a function.
|
||||||
public export
|
public export
|
||||||
ito : (s -> (i, a)) -> IndexedGetter i s a
|
ito : (s -> (i, a)) -> IndexedGetter i s a
|
||||||
ito f @{MkIsGetter _} @{ind} = lmap f . rphantom . indexed @{ind}
|
ito f @{MkIsGetter _} @{ind} = lmap f . rphantom . indexed @{ind}
|
||||||
|
|
|
@ -83,7 +83,8 @@ indexedIso @{MkIsIso _} = MkIsIso %search
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
||| Compose two indexed optics, using a function to combine the indices of each
|
||||||
|
||| optic.
|
||||||
public export
|
public export
|
||||||
icompose : IsIso p => (i -> j -> k) ->
|
icompose : IsIso p => (i -> j -> k) ->
|
||||||
IndexedOptic' p i s t a b -> IndexedOptic' (Indexed i p) j a b a' b' ->
|
IndexedOptic' p i s t a b -> IndexedOptic' (Indexed i p) j a b a' b' ->
|
||||||
|
@ -96,24 +97,36 @@ infixr 9 <.>
|
||||||
infixr 9 .>
|
infixr 9 .>
|
||||||
infixr 9 <.
|
infixr 9 <.
|
||||||
|
|
||||||
|
||| Compose two indexed optics, returning an optic indexed by a pair of indices.
|
||||||
|
|||
|
||||||
|
||| Mnemonically, the angle brackets point to the fact that we want to preserve
|
||||||
|
||| both indices.
|
||||||
public export
|
public export
|
||||||
(<.>) : IsIso p => IndexedOptic' p i s t a b -> IndexedOptic' (Indexed i p) j a b a' b' ->
|
(<.>) : IsIso p => IndexedOptic' p i s t a b -> IndexedOptic' (Indexed i p) j a b a' b' ->
|
||||||
IndexedOptic' p (i, j) s t a' b'
|
IndexedOptic' p (i, j) s t a' b'
|
||||||
(<.>) = icompose (,)
|
(<.>) = icompose (,)
|
||||||
|
|
||||||
|
||| Compose a non-indexed optic with an indexed optic.
|
||||||
|
|||
|
||||||
|
||| Mnemonically, the angle bracket points to the index that we want to preserve.
|
||||||
public export
|
public export
|
||||||
(.>) : Optic' p s t a b -> IndexedOptic' p i a b a' b' -> IndexedOptic' p i s t a' b'
|
(.>) : Optic' p s t a b -> IndexedOptic' p i a b a' b' -> IndexedOptic' p i s t a' b'
|
||||||
(.>) l l' = l . l'
|
(.>) l l' = l . l'
|
||||||
|
|
||||||
|
||| Compose an indexed optic with a non-indexed optic.
|
||||||
|
|||
|
||||||
|
||| Mnemonically, the angle bracket points to the index that we want to preserve.
|
||||||
public export
|
public export
|
||||||
(<.) : IndexedOptic' p i s t a b -> Optic' (Indexed i p) a b a' b' -> IndexedOptic' p i s t a' b'
|
(<.) : IndexedOptic' p i s t a b -> Optic' (Indexed i p) a b a' b' -> IndexedOptic' p i s t a' b'
|
||||||
(<.) l l' @{ind} = l @{Idxed} . runIndexed . l' . MkIndexed {p} . indexed @{ind}
|
(<.) l l' @{ind} = l @{Idxed} . runIndexed . l' . MkIndexed {p} . indexed @{ind}
|
||||||
|
|
||||||
|
|
||||||
|
||| Augment an optic with a constant index.
|
||||||
public export
|
public export
|
||||||
constIndex : IsIso p => i -> Optic' p s t a b -> IndexedOptic' p i s t a b
|
constIndex : IsIso p => i -> Optic' p s t a b -> IndexedOptic' p i s t a b
|
||||||
constIndex i l @{MkIsIso _} @{ind} = l . lmap (i,) . indexed @{ind}
|
constIndex i l @{MkIsIso _} @{ind} = l . lmap (i,) . indexed @{ind}
|
||||||
|
|
||||||
|
||| Modify the indices of an indexed optic.
|
||||||
public export
|
public export
|
||||||
reindexed : IsIso p => (i -> j) -> IndexedOptic' p i s t a b -> IndexedOptic' p j s t a b
|
reindexed : IsIso p => (i -> j) -> IndexedOptic' p i s t a b -> IndexedOptic' p j s t a b
|
||||||
reindexed @{MkIsIso _} f l @{ind} = l @{Idxed} . lmap (mapFst f) . indexed @{ind}
|
reindexed @{MkIsIso _} f l @{ind} = l @{Idxed} . lmap (mapFst f) . indexed @{ind}
|
||||||
|
|
|
@ -53,10 +53,16 @@ public export
|
||||||
0 Lens' : (s,a : Type) -> Type
|
0 Lens' : (s,a : Type) -> Type
|
||||||
Lens' = Simple Lens
|
Lens' = Simple Lens
|
||||||
|
|
||||||
|
||| An indexed lens allows access to the index of a focus while setting it.
|
||||||
|
|||
|
||||||
|
||| Any indexed lens can be coerced into a regular lens and used in normal lens
|
||||||
|
||| functions, but there are also special functions that take indexed lenses
|
||||||
|
||| (i.e. `iover` instead of `over`).
|
||||||
public export
|
public export
|
||||||
0 IndexedLens : (i,s,t,a,b : Type) -> Type
|
0 IndexedLens : (i,s,t,a,b : Type) -> Type
|
||||||
IndexedLens = IndexedOptic IsLens
|
IndexedLens = IndexedOptic IsLens
|
||||||
|
|
||||||
|
||| `IndexedLens'` is the `Simple` version of `IndexedLens`.
|
||||||
public export
|
public export
|
||||||
0 IndexedLens' : (i,s,a : Type) -> Type
|
0 IndexedLens' : (i,s,a : Type) -> Type
|
||||||
IndexedLens' = Simple . IndexedLens
|
IndexedLens' = Simple . IndexedLens
|
||||||
|
@ -76,16 +82,12 @@ public export
|
||||||
lens : (get : s -> a) -> (set : s -> b -> t) -> Lens s t a b
|
lens : (get : s -> a) -> (set : s -> b -> t) -> Lens s t a b
|
||||||
lens get set @{MkIsLens _} = dimap (\x => (x, get x)) (uncurry set) . second
|
lens get set @{MkIsLens _} = dimap (\x => (x, get x)) (uncurry set) . second
|
||||||
|
|
||||||
|
||| Construct an indexed lens given getter and setter functions.
|
||||||
public export
|
public export
|
||||||
ilens : (get : s -> (i, a)) -> (set : s -> b -> t) -> IndexedLens i s t a b
|
ilens : (get : s -> (i, a)) -> (set : s -> b -> t) -> IndexedLens i s t a b
|
||||||
ilens get set @{_} @{ind} = lens get set . indexed @{ind}
|
ilens get set @{_} @{ind} = lens get set . indexed @{ind}
|
||||||
|
|
||||||
|
|
||||||
public export
|
|
||||||
withIndex : i -> Lens s t a b -> IndexedLens i s t a b
|
|
||||||
withIndex i l @{MkIsLens _} @{ind} = l . lmap (i,) . indexed @{ind}
|
|
||||||
|
|
||||||
|
|
||||||
||| Extract getter and setter functions from a lens.
|
||| Extract getter and setter functions from a lens.
|
||||||
public export
|
public export
|
||||||
getLens : Lens s t a b -> (s -> a, s -> b -> t)
|
getLens : Lens s t a b -> (s -> a, s -> b -> t)
|
||||||
|
|
|
@ -43,10 +43,12 @@ public export
|
||||||
0 Optional' : (s,a : Type) -> Type
|
0 Optional' : (s,a : Type) -> Type
|
||||||
Optional' = Simple Optional
|
Optional' = Simple Optional
|
||||||
|
|
||||||
|
||| An `IndexedOptional` allows access to the index of a focus.
|
||||||
public export
|
public export
|
||||||
0 IndexedOptional : (i,s,t,a,b : Type) -> Type
|
0 IndexedOptional : (i,s,t,a,b : Type) -> Type
|
||||||
IndexedOptional = IndexedOptic IsOptional
|
IndexedOptional = IndexedOptic IsOptional
|
||||||
|
|
||||||
|
||| `IndexedOptional'` is the `Simple` version of `IndexedOptional`.
|
||||||
public export
|
public export
|
||||||
0 IndexedOptional' : (i,s,a : Type) -> Type
|
0 IndexedOptional' : (i,s,a : Type) -> Type
|
||||||
IndexedOptional' = Simple . IndexedOptional
|
IndexedOptional' = Simple . IndexedOptional
|
||||||
|
@ -74,10 +76,12 @@ public export
|
||||||
optional' : (s -> Maybe a) -> (s -> b -> s) -> Optional s s a b
|
optional' : (s -> Maybe a) -> (s -> b -> s) -> Optional s s a b
|
||||||
optional' prj = optional (\x => maybe (Left x) Right (prj x))
|
optional' prj = optional (\x => maybe (Left x) Right (prj x))
|
||||||
|
|
||||||
|
||| Construct an indexed optional from a projection and a setter function.
|
||||||
public export
|
public export
|
||||||
ioptional : (s -> Either t (i, a)) -> (s -> b -> t) -> IndexedOptional i s t a b
|
ioptional : (s -> Either t (i, a)) -> (s -> b -> t) -> IndexedOptional i s t a b
|
||||||
ioptional prj set @{_} @{ind} = optional prj set . indexed @{ind}
|
ioptional prj set @{_} @{ind} = optional prj set . indexed @{ind}
|
||||||
|
|
||||||
|
||| Construct a simple indexed optional from a projection and a setter function.
|
||||||
public export
|
public export
|
||||||
ioptional' : (s -> Maybe (i, a)) -> (s -> b -> s) -> IndexedOptional i s s a b
|
ioptional' : (s -> Maybe (i, a)) -> (s -> b -> s) -> IndexedOptional i s s a b
|
||||||
ioptional' prj = ioptional (\x => maybe (Left x) Right (prj x))
|
ioptional' prj = ioptional (\x => maybe (Left x) Right (prj x))
|
||||||
|
|
|
@ -40,6 +40,7 @@ public export
|
||||||
0 OptionalFold : (s,a : Type) -> Type
|
0 OptionalFold : (s,a : Type) -> Type
|
||||||
OptionalFold = Simple (Optic IsOptFold)
|
OptionalFold = Simple (Optic IsOptFold)
|
||||||
|
|
||||||
|
||| An `IndexedOptionalFold` returns an index while getting.
|
||||||
public export
|
public export
|
||||||
0 IndexedOptionalFold : (i,s,a : Type) -> Type
|
0 IndexedOptionalFold : (i,s,a : Type) -> Type
|
||||||
IndexedOptionalFold = Simple . IndexedOptic IsOptFold
|
IndexedOptionalFold = Simple . IndexedOptic IsOptFold
|
||||||
|
@ -56,6 +57,7 @@ folding : (s -> Maybe a) -> OptionalFold s a
|
||||||
folding f @{MkIsOptFold _} =
|
folding f @{MkIsOptFold _} =
|
||||||
contrabimap (\x => maybe (Left x) Right (f x)) Left . right
|
contrabimap (\x => maybe (Left x) Right (f x)) Left . right
|
||||||
|
|
||||||
|
||| Construct an `IndexedOptionalFold` from a function.
|
||||||
public export
|
public export
|
||||||
ifolding : (s -> Maybe (i, a)) -> IndexedOptionalFold i s a
|
ifolding : (s -> Maybe (i, a)) -> IndexedOptionalFold i s a
|
||||||
ifolding f @{MkIsOptFold _} @{ind} =
|
ifolding f @{MkIsOptFold _} @{ind} =
|
||||||
|
|
|
@ -49,10 +49,12 @@ public export
|
||||||
0 Setter' : (s,a : Type) -> Type
|
0 Setter' : (s,a : Type) -> Type
|
||||||
Setter' = Simple Setter
|
Setter' = Simple Setter
|
||||||
|
|
||||||
|
||| An indexed setter allows access to an index while setting.
|
||||||
public export
|
public export
|
||||||
0 IndexedSetter : (i,s,t,a,b : Type) -> Type
|
0 IndexedSetter : (i,s,t,a,b : Type) -> Type
|
||||||
IndexedSetter = IndexedOptic IsSetter
|
IndexedSetter = IndexedOptic IsSetter
|
||||||
|
|
||||||
|
||| `IndexedSetter'` is the `Simple` version of `IndexedSetter`.
|
||||||
public export
|
public export
|
||||||
0 IndexedSetter' : (i,s,a : Type) -> Type
|
0 IndexedSetter' : (i,s,a : Type) -> Type
|
||||||
IndexedSetter' = Simple . IndexedSetter
|
IndexedSetter' = Simple . IndexedSetter
|
||||||
|
@ -68,6 +70,7 @@ public export
|
||||||
sets : ((a -> b) -> s -> t) -> Setter s t a b
|
sets : ((a -> b) -> s -> t) -> Setter s t a b
|
||||||
sets f @{MkIsSetter _} = roam f
|
sets f @{MkIsSetter _} = roam f
|
||||||
|
|
||||||
|
||| Construct an indexed setter from a modifying function.
|
||||||
public export
|
public export
|
||||||
isets : ((i -> a -> b) -> s -> t) -> IndexedSetter i s t a b
|
isets : ((i -> a -> b) -> s -> t) -> IndexedSetter i s t a b
|
||||||
isets f @{MkIsSetter _} @{ind} = roam (f . curry) . indexed @{ind}
|
isets f @{MkIsSetter _} @{ind} = roam (f . curry) . indexed @{ind}
|
||||||
|
@ -98,12 +101,16 @@ public export
|
||||||
(%~) = over
|
(%~) = over
|
||||||
|
|
||||||
|
|
||||||
|
||| Modify the focus or focuses of an indexed optic, having access to the index.
|
||||||
public export
|
public export
|
||||||
iover : IndexedSetter i s t a b -> (i -> a -> b) -> s -> t
|
iover : IndexedSetter i s t a b -> (i -> a -> b) -> s -> t
|
||||||
iover l = l @{MkIsSetter Function} @{Idxed} . uncurry
|
iover l = l @{MkIsSetter Function} @{Idxed} . uncurry
|
||||||
|
|
||||||
infixr 4 %@~
|
infixr 4 %@~
|
||||||
|
|
||||||
|
||| Modify the focus or focuses of an indexed optic, having access to the index.
|
||||||
|
|||
|
||||||
|
||| This is the operator form of `iover`.
|
||||||
public export
|
public export
|
||||||
(%@~) : IndexedSetter i s t a b -> (i -> a -> b) -> s -> t
|
(%@~) : IndexedSetter i s t a b -> (i -> a -> b) -> s -> t
|
||||||
(%@~) = iover
|
(%@~) = iover
|
||||||
|
@ -124,12 +131,16 @@ public export
|
||||||
(.~) = set
|
(.~) = set
|
||||||
|
|
||||||
|
|
||||||
|
||| Set the focus or focuses of an indexed optic, having access to the index.
|
||||||
public export
|
public export
|
||||||
iset : IndexedSetter i s t a b -> (i -> b) -> s -> t
|
iset : IndexedSetter i s t a b -> (i -> b) -> s -> t
|
||||||
iset l = iover l . (const .)
|
iset l = iover l . (const .)
|
||||||
|
|
||||||
infix 4 .@~
|
infix 4 .@~
|
||||||
|
|
||||||
|
||| Set the focus or focuses of an indexed optic, having access to the index.
|
||||||
|
|||
|
||||||
|
||| This is the operator form of `iset`.
|
||||||
public export
|
public export
|
||||||
(.@~) : IndexedSetter i s t a b -> (i -> b) -> s -> t
|
(.@~) : IndexedSetter i s t a b -> (i -> b) -> s -> t
|
||||||
(.@~) = iset
|
(.@~) = iset
|
||||||
|
@ -215,6 +226,7 @@ public export
|
||||||
(%=) : MonadState s m => Setter s s a b -> (a -> b) -> m ()
|
(%=) : MonadState s m => Setter s s a b -> (a -> b) -> m ()
|
||||||
(%=) = modify .: over
|
(%=) = modify .: over
|
||||||
|
|
||||||
|
||| Modify the focus of an optic within a state monad, having access to the index.
|
||||||
public export
|
public export
|
||||||
(%@=) : MonadState s m => IndexedSetter i s s a b -> (i -> a -> b) -> m ()
|
(%@=) : MonadState s m => IndexedSetter i s s a b -> (i -> a -> b) -> m ()
|
||||||
(%@=) = modify .: iover
|
(%@=) = modify .: iover
|
||||||
|
@ -224,6 +236,7 @@ public export
|
||||||
(.=) : MonadState s m => Setter s s a b -> b -> m ()
|
(.=) : MonadState s m => Setter s s a b -> b -> m ()
|
||||||
(.=) = modify .: set
|
(.=) = modify .: set
|
||||||
|
|
||||||
|
||| Set the focus of an optic within a state monad, having access to the index.
|
||||||
public export
|
public export
|
||||||
(.@=) : MonadState s m => IndexedSetter i s s a b -> (i -> b) -> m ()
|
(.@=) : MonadState s m => IndexedSetter i s s a b -> (i -> b) -> m ()
|
||||||
(.@=) = modify .: iset
|
(.@=) = modify .: iset
|
||||||
|
|
|
@ -44,10 +44,13 @@ public export
|
||||||
0 Traversal' : (s,a : Type) -> Type
|
0 Traversal' : (s,a : Type) -> Type
|
||||||
Traversal' = Simple Traversal
|
Traversal' = Simple Traversal
|
||||||
|
|
||||||
|
||| An indexed traversal allows access to the indices of the values as they are
|
||||||
|
||| being modified.
|
||||||
public export
|
public export
|
||||||
0 IndexedTraversal : (i,s,t,a,b : Type) -> Type
|
0 IndexedTraversal : (i,s,t,a,b : Type) -> Type
|
||||||
IndexedTraversal = IndexedOptic IsTraversal
|
IndexedTraversal = IndexedOptic IsTraversal
|
||||||
|
|
||||||
|
||| `IndexedTraversal'` is the `Simple` version of `IndexedTraversal`.
|
||||||
public export
|
public export
|
||||||
0 IndexedTraversal' : (i,s,a : Type) -> Type
|
0 IndexedTraversal' : (i,s,a : Type) -> Type
|
||||||
IndexedTraversal' = Simple . IndexedTraversal
|
IndexedTraversal' = Simple . IndexedTraversal
|
||||||
|
@ -58,6 +61,8 @@ IndexedTraversal' = Simple . IndexedTraversal
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
||| Convert a traversal into an indexed traversal, adding an index for the
|
||||||
|
||| ordinal position of the focus.
|
||||||
public export
|
public export
|
||||||
iordinal : Num i => Traversal s t a b -> IndexedTraversal i s t a b
|
iordinal : Num i => Traversal s t a b -> IndexedTraversal i s t a b
|
||||||
iordinal @{_} l @{MkIsTraversal _} @{ind} = wander (func . curry) . indexed @{ind}
|
iordinal @{_} l @{MkIsTraversal _} @{ind} = wander (func . curry) . indexed @{ind}
|
||||||
|
@ -71,6 +76,7 @@ public export
|
||||||
traversed : Traversable t => Traversal (t a) (t b) a b
|
traversed : Traversable t => Traversal (t a) (t b) a b
|
||||||
traversed @{_} @{MkIsTraversal _} = traverse'
|
traversed @{_} @{MkIsTraversal _} = traverse'
|
||||||
|
|
||||||
|
||| Derive an indexed traversal from a `Traversable` implementation.
|
||||||
public export
|
public export
|
||||||
itraversed : Num i => Traversable t => IndexedTraversal i (t a) (t b) a b
|
itraversed : Num i => Traversable t => IndexedTraversal i (t a) (t b) a b
|
||||||
itraversed = iordinal traversed
|
itraversed = iordinal traversed
|
||||||
|
@ -96,6 +102,8 @@ public export
|
||||||
traverseOf : Applicative f => Traversal s t a b -> (a -> f b) -> s -> f t
|
traverseOf : Applicative f => Traversal s t a b -> (a -> f b) -> s -> f t
|
||||||
traverseOf l = applyStar . l . MkStar {f}
|
traverseOf l = applyStar . l . MkStar {f}
|
||||||
|
|
||||||
|
||| Map each focus of a traversal to a computation with acces to the index,
|
||||||
|
||| evaluate those computations and combine the results.
|
||||||
public export
|
public export
|
||||||
itraverseOf : Applicative f => IndexedTraversal i s t a b -> (i -> a -> f b) -> s -> f t
|
itraverseOf : Applicative f => IndexedTraversal i s t a b -> (i -> a -> f b) -> s -> f t
|
||||||
itraverseOf l = traverseOf (l @{%search} @{Idxed}) . uncurry
|
itraverseOf l = traverseOf (l @{%search} @{Idxed}) . uncurry
|
||||||
|
@ -105,6 +113,7 @@ public export
|
||||||
forOf : Applicative f => Traversal s t a b -> s -> (a -> f b) -> f t
|
forOf : Applicative f => Traversal s t a b -> s -> (a -> f b) -> f t
|
||||||
forOf = flip . traverseOf
|
forOf = flip . traverseOf
|
||||||
|
|
||||||
|
||| A version of `itraverseOf` but with the arguments flipped.
|
||||||
public export
|
public export
|
||||||
iforOf : Applicative f => IndexedTraversal i s t a b -> s -> (i -> a -> f b) -> f t
|
iforOf : Applicative f => IndexedTraversal i s t a b -> s -> (i -> a -> f b) -> f t
|
||||||
iforOf = flip . itraverseOf
|
iforOf = flip . itraverseOf
|
||||||
|
@ -161,6 +170,7 @@ failover l f x =
|
||||||
(b, y) = traverseOf l ((True,) . f) x
|
(b, y) = traverseOf l ((True,) . f) x
|
||||||
in guard b $> y
|
in guard b $> y
|
||||||
|
|
||||||
|
||| Try to map over an indexed traversal, failing if the traversal has no focuses.
|
||||||
public export
|
public export
|
||||||
ifailover : Alternative f => IndexedTraversal i s t a b -> (i -> a -> b) -> s -> f t
|
ifailover : Alternative f => IndexedTraversal i s t a b -> (i -> a -> b) -> s -> f t
|
||||||
ifailover l = failover (l @{%search} @{Idxed}) . uncurry
|
ifailover l = failover (l @{%search} @{Idxed}) . uncurry
|
||||||
|
@ -181,6 +191,12 @@ partsOf : Traversal s t a a -> Lens s t (List a) (List a)
|
||||||
partsOf l = lens (runForget $ l $ MkForget pure)
|
partsOf l = lens (runForget $ l $ MkForget pure)
|
||||||
(flip evalState . traverseOf l partsOf_update)
|
(flip evalState . traverseOf l partsOf_update)
|
||||||
|
|
||||||
|
||| Convert an indexed traversal into an indexed lens over a list of values, with
|
||||||
|
||| access to a list of indices.
|
||||||
|
|||
|
||||||
|
||| Note that this is only a true lens if the invariant of the list's length is
|
||||||
|
||| maintained. You should avoid mapping `over` this lens with a function that
|
||||||
|
||| changes the list's length.
|
||||||
public export
|
public export
|
||||||
ipartsOf : IndexedTraversal i s t a a -> IndexedLens (List i) s t (List a) (List a)
|
ipartsOf : IndexedTraversal i s t a a -> IndexedLens (List i) s t (List a) (List a)
|
||||||
ipartsOf l = ilens (unzip . (runForget $ l @{%search} @{Idxed} $ MkForget pure))
|
ipartsOf l = ilens (unzip . (runForget $ l @{%search} @{Idxed} $ MkForget pure))
|
||||||
|
@ -198,6 +214,18 @@ singular l = optional' (runForget $ l (MkForget Just)) set
|
||||||
set str x = evalState True $ traverseOf l
|
set str x = evalState True $ traverseOf l
|
||||||
(\y => if !get then put False $> x else pure y) str
|
(\y => if !get then put False $> x else pure y) str
|
||||||
|
|
||||||
|
||| Construct an indexed optional that focuses on the first value of an
|
||||||
|
||| indexed traversal.
|
||||||
|
|||
|
||||||
|
||| For the fold version of this, see `ipre`.
|
||||||
|
public export
|
||||||
|
isingular : IndexedTraversal' i s a -> IndexedOptional' i s a
|
||||||
|
isingular l = ioptional' (runForget $ l @{%search} @{Idxed} (MkForget Just)) set
|
||||||
|
where
|
||||||
|
set : s -> a -> s
|
||||||
|
set str x = evalState True $ itraverseOf l
|
||||||
|
(\_,y => if !get then put False $> x else pure y) str
|
||||||
|
|
||||||
||| Filter the focuses of a traversal by a predicate on their ordinal positions.
|
||| Filter the focuses of a traversal by a predicate on their ordinal positions.
|
||||||
public export
|
public export
|
||||||
elementsOf : Traversal s t a a -> (Nat -> Bool) -> Traversal s t a a
|
elementsOf : Traversal s t a a -> (Nat -> Bool) -> Traversal s t a a
|
||||||
|
|
|
@ -6,10 +6,12 @@ import public Control.Lens
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
||| A prism to the left of an `Either`.
|
||||||
public export
|
public export
|
||||||
Left_ : Prism (Either a c) (Either b c) a b
|
Left_ : Prism (Either a c) (Either b c) a b
|
||||||
Left_ @{MkIsPrism _} = left
|
Left_ @{MkIsPrism _} = left
|
||||||
|
|
||||||
|
||| A prism to the right of an `Either`.
|
||||||
public export
|
public export
|
||||||
Right_ : Prism (Either c a) (Either c b) a b
|
Right_ : Prism (Either c a) (Either c b) a b
|
||||||
Right_ @{MkIsPrism _} = right
|
Right_ @{MkIsPrism _} = right
|
||||||
|
|
|
@ -29,15 +29,18 @@ stripSuffix qs xs0 = go xs0 zs
|
||||||
go [] _ = Nothing
|
go [] _ = Nothing
|
||||||
|
|
||||||
|
|
||||||
|
||| A prism that strips a prefix from a list of values.
|
||||||
public export
|
public export
|
||||||
prefixed : Eq a => List a -> Prism' (List a) (List a)
|
prefixed : Eq a => List a -> Prism' (List a) (List a)
|
||||||
prefixed xs = prism' (xs ++) (stripPrefix xs)
|
prefixed xs = prism' (xs ++) (stripPrefix xs)
|
||||||
|
|
||||||
|
||| A prism that strips a suffix from a list of values.
|
||||||
public export
|
public export
|
||||||
suffixed : Eq a => List a -> Prism' (List a) (List a)
|
suffixed : Eq a => List a -> Prism' (List a) (List a)
|
||||||
suffixed xs = prism' (++ xs) (stripSuffix xs)
|
suffixed xs = prism' (++ xs) (stripSuffix xs)
|
||||||
|
|
||||||
|
|
||||||
|
||| An isomorphism between a list and its reverse.
|
||||||
public export
|
public export
|
||||||
reversed : Iso (List a) (List b) (List a) (List b)
|
reversed : Iso (List a) (List b) (List a) (List b)
|
||||||
reversed = iso reverse reverse
|
reversed = iso reverse reverse
|
||||||
|
|
|
@ -7,10 +7,12 @@ import public Control.Lens
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
||| A prism of the `Nothing` case of a `Maybe`.
|
||||||
public export
|
public export
|
||||||
Nothing_ : Prism' (Maybe a) ()
|
Nothing_ : Prism' (Maybe a) ()
|
||||||
Nothing_ = prism' (const Nothing) (guard . isNothing)
|
Nothing_ = prism' (const Nothing) (guard . isNothing)
|
||||||
|
|
||||||
|
||| A prism of the `Just` case of a `Maybe`.
|
||||||
public export
|
public export
|
||||||
Just_ : Prism (Maybe a) (Maybe b) a b
|
Just_ : Prism (Maybe a) (Maybe b) a b
|
||||||
Just_ = prism Just $ \case
|
Just_ = prism Just $ \case
|
||||||
|
@ -19,6 +21,8 @@ Just_ = prism Just $ \case
|
||||||
|
|
||||||
infixl 9 .?
|
infixl 9 .?
|
||||||
|
|
||||||
|
||| The composition `l .? l'` is equivalent to `l . Just_ . l'`.
|
||||||
|
||| Useful for optics who focus type is a `Maybe`, such as `at`.
|
||||||
public export
|
public export
|
||||||
(.?) : IsPrism p => Optic' p s t (Maybe a) (Maybe b) -> Optic' p a b a' b' -> Optic' p s t a' b'
|
(.?) : IsPrism p => Optic' p s t (Maybe a) (Maybe b) -> Optic' p a b a' b' -> Optic' p s t a' b'
|
||||||
l .? l' = l . Just_ . l'
|
l .? l' = l . Just_ . l'
|
||||||
|
|
|
@ -7,19 +7,23 @@ import public Control.Lens
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
||| A lens to the first element of a pair.
|
||||||
public export
|
public export
|
||||||
fst_ : Lens (a, c) (b, c) a b
|
fst_ : Lens (a, c) (b, c) a b
|
||||||
fst_ @{MkIsLens _} = first
|
fst_ @{MkIsLens _} = first
|
||||||
|
|
||||||
|
||| A lens to the second element of a pair.
|
||||||
public export
|
public export
|
||||||
snd_ : Lens (c, a) (c, b) a b
|
snd_ : Lens (c, a) (c, b) a b
|
||||||
snd_ @{MkIsLens _} = second
|
snd_ @{MkIsLens _} = second
|
||||||
|
|
||||||
|
|
||||||
|
||| An indexed lens to the first element of a pair, indexed by the other element.
|
||||||
public export
|
public export
|
||||||
ifst_ : IndexedLens i (a, i) (b, i) a b
|
ifst_ : IndexedLens i (a, i) (b, i) a b
|
||||||
ifst_ = ilens swap (flip $ mapFst . const)
|
ifst_ = ilens swap (flip $ mapFst . const)
|
||||||
|
|
||||||
|
||| An indexed lens to the second element of a pair, indexed by the other element.
|
||||||
public export
|
public export
|
||||||
isnd_ : IndexedLens i (i, a) (i, b) a b
|
isnd_ : IndexedLens i (i, a) (i, b) a b
|
||||||
isnd_ = ilens id (flip $ mapSnd . const)
|
isnd_ = ilens id (flip $ mapSnd . const)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Control.Lens
|
||||||
%default total
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
||| An isomorphism between a `Vect` and its reverse.
|
||||||
public export
|
public export
|
||||||
reversed : Iso (Vect n a) (Vect n b) (Vect n a) (Vect n b)
|
reversed : Iso (Vect n a) (Vect n b) (Vect n a) (Vect n b)
|
||||||
reversed = iso reverse reverse
|
reversed = iso reverse reverse
|
||||||
|
|
Loading…
Reference in a new issue