{-| Minimal redefine + re-export of a lens package, fclabels -} {-# LANGUAGE TypeOperators, RankNTypes #-} module CHR.Data.Lens.MicroLens ( (:->) , Lens -- , lens -- * Access , (^*) , (^.) , getL , (^=) , (^$=) {- , (=.) -} , (=:) , (=$:) , modifyAndGet , (=$^:) , modL , getl -- * Misc {- , focus -} , mkLabel -- * Tuple accessors , fstl , sndl , fst3l , snd3l , trd3l -- * Wrappers , isoMb , isoMbWithDefault ) where import qualified Control.Monad.State as MS import Lens.Micro hiding (Lens, lens) import qualified Lens.Micro as L import Lens.Micro.Mtl import Lens.Micro.TH import Language.Haskell.TH import CHR.Utils -- * Type aliases type Lens a b = Lens' a b type a :-> b = Lens' a b lens :: (a -> b) -> (a -> b -> a) -> (a :-> b) lens = L.lens {-# INLINE lens #-} -- * Operator interface for composition infixl 9 ^* -- | composition alias (^*) :: (a :-> b) -> (b :-> c) -> (a :-> c) f1 ^* f2 = f1 . f2 {-# INLINE (^*) #-} {- -- * Operator interface for functional part (occasionally similar to Data.Lens) infixl 8 ^. -- | functional getter, which acts like a field accessor (^.) :: a -> (a :-> b) -> b a ^. f = get f a {-# INLINE (^.) #-} -} -- | Alias for 'get' to avoid conflict with state get; not happy choice because of 'getl' getL :: (f :-> a) -> f -> a getL = flip (^.) {-# INLINE getL #-} infixr 4 ^= -- | functional setter, which acts like a field assigner (^=) :: (a :-> b) -> b -> a -> a (^=) = set {-# INLINE (^=) #-} infixr 4 ^$= -- | functional modify (^$=) :: (a :-> b) -> (b -> b) -> a -> a (^$=) = over {-# INLINE (^$=) #-} {- -} -- * Operator interface for monadic part (occasionally similar to Data.Lens) infixr 4 =$^: -- | monadic modify & set & get (=$^:), modL, modifyAndGet :: MS.MonadState f m => (f :-> o) -> (o -> (a,o)) -> m a l =$^: f = do old <- use l let (res,new) = f old l =: new return res {-# INLINE (=$^:) #-} modL = (=$^:) {-# INLINE modL #-} modifyAndGet = (=$^:) {-# INLINE modifyAndGet #-} -- | monadic get getl :: MS.MonadState f m => (f :-> o) -> m o getl = use infixr 4 =: -- | monadic set (=:) :: MS.MonadState f m => (f :-> o) -> o -> m () (=:) = (.=) {-# INLINE (=:) #-} infixr 4 =$: -- | monadic modify & set (=$:) :: MS.MonadState f m => (f :-> o) -> (o -> o) -> m () (=$:) = modifying {-# INLINE (=$:) #-} {- -- | Zoom state in on substructure. This regretfully does not really work, because of MonadState fundep. focus :: (MS.MonadState a m, MS.MonadState b m) => (a :-> b) -> m c -> m c focus f m = do a <- MS.get (b,c) <- do {MS.put (get f a) ; c <- m ; b <- MS.get ; return (b,c)} MS.put $ set f b a return c -- | Alias for 'gets' avoiding conflict with MonadState getl :: MS.MonadState f m => (f :-> o) -> m o getl = M.gets {-# INLINE getl #-} -} -- * Misc mkLabel :: Name -> Q [Dec] mkLabel = makeLenses -- * Tuple fstl :: Lens (a,b) a fstl = (_1) {-# INLINE fstl #-} sndl :: Lens (a,b) b sndl = (_2) {-# INLINE sndl #-} fst3l :: Lens (a,b,c) a fst3l = (_1) {-# INLINE fst3l #-} snd3l :: Lens (a,b,c) b snd3l = (_2) {-# INLINE snd3l #-} trd3l :: Lens (a,b,c) c trd3l = (_3) {-# INLINE trd3l #-} -- * Wrappers -- | Wrapper around a Maybe with a default in case of Nothing isoMbWithDefault :: o -> (f :-> Maybe o) -> (f :-> o) -- isoMbWithDefault dflt f = iso (Iso (maybe dflt id) (Just)) . f isoMbWithDefault dflt f = lens (\a -> maybe dflt id $ a ^. f) (\a b -> set f (Just b) a) -- | Wrapper around a Maybe with an embedded panic in case of Nothing, with a panic message isoMb :: String -> (f :-> Maybe o) -> (f :-> o) -- isoMb msg f = iso (Iso (panicJust msg) (Just)) . f isoMb msg f = lens (\a -> panicJust msg $ a ^. f) (\a b -> set f (Just b) a)