idris2-lens/src/Control/Lens/OptionalFold.idr

58 lines
1.7 KiB
Idris
Raw Normal View History

module Control.Lens.OptionalFold
2023-04-12 11:55:22 -04:00
import Data.Bicontravariant
import Data.Profunctor
import Data.Profunctor.Costrong
import Control.Lens.Optic
import Control.Lens.Optional
import Control.Lens.Getter
%default total
2023-04-12 22:41:23 -04:00
------------------------------------------------------------------------------
-- Type definitions
------------------------------------------------------------------------------
public export
record IsOptFold p where
constructor MkIsOptFold
runIsOptFold : (Strong p, Choice p, Cochoice p, Bicontravariant p)
export %hint
optFoldToOptional : IsOptFold p => IsOptional p
optFoldToOptional @{MkIsOptFold _} = MkIsOptional %search
export %hint
optFoldToGetter : IsOptFold p => IsGetter p
optFoldToGetter @{MkIsOptFold _} = MkIsGetter %search
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`.
public export
0 OptionalFold : (s,a : Type) -> Type
2023-04-12 11:59:51 -04:00
OptionalFold = Simple (Optic IsOptFold)
2023-04-12 22:41:23 -04:00
------------------------------------------------------------------------------
-- Utilities for OptionalFolds
------------------------------------------------------------------------------
||| Construct an `OptionalFold` from a function.
public export
folding : (s -> Maybe a) -> OptionalFold s a
folding f @{MkIsOptFold _} =
contrabimap (\x => maybe (Left x) Right (f x)) Left . right
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.
public export
filtered : (a -> Bool) -> OptionalFold a a
filtered p = folding (\x => if p x then Just x else Nothing)