fresnel-0.0.0.0: src/Fresnel/OptionalFold.hs
{-# LANGUAGE RankNTypes #-}
module Fresnel.OptionalFold
( -- * Optional folds
OptionalFold
, IsOptionalFold
-- * Construction
, folding
, filtered
-- * Elimination
, is
, isn't
, traverseOf_
, Failover(..)
) where
import Control.Applicative ((<|>))
import Data.Functor (void)
import Data.Maybe (isJust, isNothing)
import Data.Profunctor
import Fresnel.Bifunctor.Contravariant
import Fresnel.Fold (preview)
import Fresnel.Optic
import Fresnel.OptionalFold.Internal
-- Optional folds
type OptionalFold s a = forall p . IsOptionalFold p => Optic' p s a
-- Construction
folding :: (s -> Maybe a) -> OptionalFold s a
folding f = contrabimap ((`maybe` Right) . Left <*> f) Left . right'
filtered :: (a -> Bool) -> OptionalFold a a
filtered p = folding (\ a -> if p a then Just a else Nothing)
-- Elimination
is :: OptionalFold s a -> (s -> Bool)
is o = isNothing . preview o
isn't :: OptionalFold s a -> (s -> Bool)
isn't o = isJust . preview o
traverseOf_ :: Functor f => OptionalFold s a -> ((forall x . x -> f x) -> (a -> f u) -> (s -> f ()))
traverseOf_ o point f s = maybe (point ()) (void . f) (preview o s)
newtype Failover s a = Failover { getFailover :: OptionalFold s a }
instance Semigroup (Failover s a) where
Failover a1 <> Failover a2 = Failover (folding (\ s -> preview a1 s <|> preview a2 s))