{-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE AllowAmbiguousTypes #-} module Trek.Lens ( selecting , mounting , focusing , (%>) ) where import Control.Lens import Trek import Control.Monad.State import Control.Monad.Logic -- infixr 4 <+@> -- (<+@>) :: (Indexable i p, Contravariant f, Applicative f) => IndexedFold i s a -> IndexedFold i s a -> p a (f a) -> s -> f s -- fldA <+@> fldB = conjoined (fldA <+> fldB) (ifolding (\s -> (s ^@.. fldA) <> (s ^@.. fldB))) -- infixr 4 <+> -- -- | (<+>) allows you to append multiple folds into one -- (<+>) :: Fold s a -> Fold s a -> Fold s a -- fldA <+> fldB = (folding (\s -> (s ^.. fldA) <> (s ^.. fldB))) -- | Optical version of 'select'/'selectEach'. Iterates over all result(s) of the provided optic in the structure. -- Accepts a Getter, Traversal, Prism, Iso or Fold. selecting :: Monad m => Fold s a -> TrekT s m a selecting fld = selectEach (toListOf fld) -- | Allows sequencing a tuple or list of Trek blocks into the values that they return. -- selectAll :: Monad m => Each x y (TrekT s m b) b => x -> TrekT s m y -- selectAll = sequenceAOf each -- | The optical version of 'mount'/'mountEach'. Runs a 'TrekT' block over each focus of -- the provided optic. -- All state updates are discarded. mounting :: Monad m => Fold t s -> TrekT s m a -> TrekT t m a mounting fld exp = do xs <- collect (selecting fld) withEach xs exp infixr 4 `focusing` -- | Run a 'TrekT' block over a subset of your state. Unlike 'using', updates to the state -- are KEPT. focusing :: forall s t m a. (Monad m) => Traversal' s t -> TrekT t m a -> TrekT s m a focusing trav (TrekT logt) = do let st = observeAllT logt let zst :: StateT s m [a] = zoom trav st xs <- TrekT (lift zst) iter xs -- Infix alias for 'focusing' infixr 4 %> -- | Zoom a trek through a traversal (%>) :: forall m s t a. Monad m => Traversal' s t -> TrekT t m a -> TrekT s m a (%>) = focusing