2023-04-12 11:34:33 -04:00
|
|
|
module Control.Lens.OptionalFold
|
|
|
|
|
2023-04-12 11:55:22 -04:00
|
|
|
import Data.Bicontravariant
|
2023-04-12 11:34:33 -04:00
|
|
|
import Data.Profunctor
|
|
|
|
import Data.Profunctor.Costrong
|
|
|
|
import Control.Lens.Optic
|
2023-04-19 14:07:50 -04:00
|
|
|
import Control.Lens.Indexed
|
2023-04-12 11:34:33 -04:00
|
|
|
import Control.Lens.Optional
|
|
|
|
import Control.Lens.Getter
|
|
|
|
|
|
|
|
%default total
|
|
|
|
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Type definitions
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
record IsOptFold p where
|
|
|
|
constructor MkIsOptFold
|
2023-04-20 11:15:39 -04:00
|
|
|
runIsOptFold : (Strong p, Choice p, Bicontravariant p)
|
2023-04-12 11:34:33 -04:00
|
|
|
|
|
|
|
export %hint
|
|
|
|
optFoldToOptional : IsOptFold p => IsOptional p
|
|
|
|
optFoldToOptional @{MkIsOptFold _} = MkIsOptional %search
|
|
|
|
|
|
|
|
export %hint
|
|
|
|
optFoldToGetter : IsOptFold p => IsGetter p
|
|
|
|
optFoldToGetter @{MkIsOptFold _} = MkIsGetter %search
|
|
|
|
|
2023-04-20 11:15:39 -04:00
|
|
|
export %hint
|
|
|
|
indexedOptFold : IsOptFold p => IsOptFold (Indexed i p)
|
|
|
|
indexedOptFold @{MkIsOptFold _} = MkIsOptFold %search
|
|
|
|
|
2023-04-12 11:34:33 -04:00
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| An `OptionalFold` is a getter that may not return a focus value.
|
|
|
|
||| `OptionalFold s a` is equivalent to `s -> Maybe a`.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
0 OptionalFold : (s,a : Type) -> Type
|
2023-04-12 11:59:51 -04:00
|
|
|
OptionalFold = Simple (Optic IsOptFold)
|
2023-04-12 11:34:33 -04:00
|
|
|
|
2023-04-19 14:07:50 -04:00
|
|
|
public export
|
|
|
|
0 IndexedOptionalFold : (i,s,a : Type) -> Type
|
|
|
|
IndexedOptionalFold = Simple . IndexedOptic IsOptFold
|
|
|
|
|
2023-04-12 11:34:33 -04:00
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Utilities for OptionalFolds
|
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
||| Construct an `OptionalFold` from a function.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
folding : (s -> Maybe a) -> OptionalFold s a
|
|
|
|
folding f @{MkIsOptFold _} =
|
|
|
|
contrabimap (\x => maybe (Left x) Right (f x)) Left . right
|
|
|
|
|
2023-04-19 14:07:50 -04:00
|
|
|
public export
|
|
|
|
ifolding : (s -> Maybe (i, a)) -> IndexedOptionalFold i s a
|
|
|
|
ifolding f @{MkIsOptFold _} @{ind} =
|
|
|
|
contrabimap (\x => maybe (Left x) Right (f x)) Left . right . indexed @{ind}
|
|
|
|
|
|
|
|
|
2023-04-12 22:41:23 -04:00
|
|
|
||| Construct an `OptionalFold` that can be used to filter the focuses
|
|
|
|
||| of another optic.
|
|
|
|
|||
|
|
|
|
||| To be more specific, this optic passes the value through unchanged if it
|
|
|
|
||| satisfies the predicate and returns no values if it does not.
|
2023-04-12 11:34:33 -04:00
|
|
|
public export
|
|
|
|
filtered : (a -> Bool) -> OptionalFold a a
|
|
|
|
filtered p = folding (\x => if p x then Just x else Nothing)
|