2023-04-12 11:34:33 -04:00
|
|
|
module Control.Lens.Traversal
|
|
|
|
|
|
|
|
import Control.Monad.State
|
|
|
|
import Data.Zippable
|
|
|
|
import Data.Profunctor
|
|
|
|
import Data.Profunctor.Traversing
|
2023-04-12 11:55:22 -04:00
|
|
|
import Control.Applicative.Backwards
|
2023-04-12 11:34:33 -04:00
|
|
|
import Control.Lens.Optic
|
|
|
|
import Control.Lens.Optional
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Type definitions
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
record IsTraversal p where
|
|
|
|
constructor MkIsTraversal
|
|
|
|
runIsTraversal : Traversing p
|
|
|
|
|
|
|
|
export %hint
|
|
|
|
traversalToOptional : IsTraversal p => IsOptional p
|
|
|
|
traversalToOptional @{MkIsTraversal _} = MkIsOptional %search
|
|
|
|
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| A traversal is a lens that may have more than one focus.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
0 Traversal : (s,t,a,b : Type) -> Type
|
|
|
|
Traversal = Optic IsTraversal
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| `Traversal'` is the `Simple` version of `Traversal`.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
0 Traversal' : (s,a : Type) -> Type
|
2023-04-12 11:59:51 -04:00
|
|
|
Traversal' = Simple Traversal
|
2023-04-12 11:34:33 -04:00
|
|
|
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Utilities for traversals
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
||| Derive a traversal from a `Traversable` implementation.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
traversed : Traversable t => Traversal (t a) (t b) a b
|
|
|
|
traversed @{_} @{MkIsTraversal _} = traverse'
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Reverse the order of a traversal's focuses.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
backwards : Traversal s t a b -> Traversal s t a b
|
|
|
|
backwards l @{MkIsTraversal _} = wander func
|
|
|
|
where
|
|
|
|
func : Applicative f => (a -> f b) -> s -> f t
|
|
|
|
func fn = forwards . applyStar {f = Backwards f} (l $ MkStar (MkBackwards . fn))
|
|
|
|
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Map each focus of a traversal to a computation, evaluate those computations
|
|
|
|
||| and combine the results.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
traverseOf : Applicative f => Traversal s t a b -> (a -> f b) -> s -> f t
|
|
|
|
traverseOf l = applyStar . l . MkStar {f}
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| A version of `traverseOf` but with the arguments flipped.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
forOf : Applicative f => Traversal s t a b -> s -> (a -> f b) -> f t
|
|
|
|
forOf l = flip $ traverseOf l
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Evaluate each computation within the traversal and collect the results.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
sequenceOf : Applicative f => Traversal s t (f a) a -> s -> f t
|
|
|
|
sequenceOf l = traverseOf l id
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Fold across the focuses of a traversal from the leftmost focus, providing a
|
|
|
|
||| replacement value for each focus, and return the final accumulator along
|
|
|
|
||| with the new structure.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
mapAccumLOf : Traversal s t a b -> (acc -> a -> (acc, b)) -> acc -> s -> (acc, t)
|
|
|
|
mapAccumLOf l f z =
|
|
|
|
let g = state . flip f
|
|
|
|
in runState z . traverseOf l g
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Fold across the focuses of a traversal from the rightmost focus, providing a
|
|
|
|
||| replacement value for each focus, and return the final accumulator along
|
|
|
|
||| with the new structure.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
mapAccumROf : Traversal s t a b -> (acc -> a -> (acc, b)) -> acc -> s -> (acc, t)
|
|
|
|
mapAccumROf l f z =
|
|
|
|
let g = MkBackwards {f=State acc} . state . flip f
|
|
|
|
in runState z . forwards . traverseOf l g
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Fold across the focuses of a traversal from the left, returning each
|
|
|
|
||| intermediate value of the fold.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
scanl1Of : Traversal s t a a -> (a -> a -> a) -> s -> t
|
|
|
|
scanl1Of l f =
|
|
|
|
let step : Maybe a -> a -> (Maybe a, a)
|
|
|
|
step Nothing x = (Just x, x)
|
|
|
|
step (Just s) x = let r = f s x in (Just r, r)
|
|
|
|
in snd . mapAccumLOf l step Nothing
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Fold across the focuses of a traversal from the right, returning each
|
|
|
|
||| intermediate value of the fold.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
scanr1Of : Traversal s t a a -> (a -> a -> a) -> s -> t
|
|
|
|
scanr1Of l f =
|
|
|
|
let step : Maybe a -> a -> (Maybe a, a)
|
|
|
|
step Nothing x = (Just x, x)
|
|
|
|
step (Just s) x = let r = f s x in (Just r, r)
|
|
|
|
in snd . mapAccumROf l step Nothing
|