packages feed

hierarchy 0.1.1 → 0.2.0

raw patch · 4 files changed

+209/−65 lines, 4 filesdep +transformers-compatPVP ok

version bump matches the API change (PVP)

Dependencies added: transformers-compat

API changes (from Hackage documentation)

- Control.Cond: instance Monad m => MonadReader a (CondT a m)
- Control.Cond: instance Monad m => MonadState a (CondT a m)
+ Control.Cond: class Monad m => MonadQuery a m | m -> a
+ Control.Cond: instance (Error e, MonadQuery r m) => MonadQuery r (ErrorT e m)
+ Control.Cond: instance (MonadQuery r m, Monoid w) => MonadQuery r (RWST r w s m)
+ Control.Cond: instance (Monoid w, MonadQuery r m) => MonadQuery r (WriterT w m)
+ Control.Cond: instance Monad m => MonadQuery a (CondT a m)
+ Control.Cond: instance Monad m => MonadZip (CondT a m)
+ Control.Cond: instance MonadCont m => MonadCont (CondT a m)
+ Control.Cond: instance MonadError e m => MonadError e (CondT a m)
+ Control.Cond: instance MonadFix m => MonadFix (CondT a m)
+ Control.Cond: instance MonadQuery r m => MonadQuery r (ExceptT e m)
+ Control.Cond: instance MonadQuery r m => MonadQuery r (IdentityT m)
+ Control.Cond: instance MonadQuery r m => MonadQuery r (ListT m)
+ Control.Cond: instance MonadQuery r m => MonadQuery r (MaybeT m)
+ Control.Cond: instance MonadQuery r m => MonadQuery r (ReaderT r m)
+ Control.Cond: instance MonadQuery r m => MonadQuery r (StateT s m)
+ Control.Cond: instance MonadQuery r' m => MonadQuery r' (ContT r m)
+ Control.Cond: instance MonadReader r m => MonadReader r (CondT a m)
+ Control.Cond: instance MonadState s m => MonadState s (CondT a m)
+ Control.Cond: instance MonadWriter w m => MonadWriter w (CondT a m)
+ Control.Cond: queries :: MonadQuery a m => (a -> b) -> m b
+ Control.Cond: query :: MonadQuery a m => m a
+ Control.Cond: update :: MonadQuery a m => a -> m ()
- Control.Cond: and_ :: Monad m => [CondT a m r] -> CondT a m ()
+ Control.Cond: and_ :: MonadPlus m => [m r] -> m ()
- Control.Cond: apply :: (MonadPlus m, MonadReader a m) => (a -> m (Maybe r)) -> m r
+ Control.Cond: apply :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe r)) -> m r
- Control.Cond: consider :: (MonadPlus m, MonadState a m) => (a -> m (Maybe (r, a))) -> m r
+ Control.Cond: consider :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe (r, a))) -> m r
- Control.Cond: guardM_ :: (MonadPlus m, MonadReader a m) => (a -> m Bool) -> m ()
+ Control.Cond: guardM_ :: (MonadPlus m, MonadQuery a m) => (a -> m Bool) -> m ()
- Control.Cond: guard_ :: (MonadPlus m, MonadReader a m) => (a -> Bool) -> m ()
+ Control.Cond: guard_ :: (MonadPlus m, MonadQuery a m) => (a -> Bool) -> m ()
- Control.Cond: if_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m s -> CondT a m s
+ Control.Cond: if_ :: MonadPlus m => m r -> m s -> m s -> m s
- Control.Cond: matches :: (Monad m, Functor m) => CondT a m r -> CondT a m Bool
+ Control.Cond: matches :: MonadPlus m => m r -> m Bool
- Control.Cond: not_ :: Monad m => CondT a m r -> CondT a m ()
+ Control.Cond: not_ :: MonadPlus m => m r -> m ()
- Control.Cond: or_ :: Monad m => [CondT a m r] -> CondT a m r
+ Control.Cond: or_ :: MonadPlus m => [m r] -> m r
- Control.Cond: unless_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m ()
+ Control.Cond: unless_ :: MonadPlus m => m r -> m s -> m ()
- Control.Cond: when_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m ()
+ Control.Cond: when_ :: MonadPlus m => m r -> m s -> m ()

Files

Control/Cond.hs view
@@ -1,14 +1,18 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecursiveDo #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} +{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}+ module Control.Cond     ( CondT, Cond @@ -16,7 +20,7 @@     , runCondT, runCond, applyCondT      -- * Promotions-    , guardM, guard_, guardM_, apply, consider+    , MonadQuery(..), guardM, guard_, guardM_, apply, consider      -- * Basic conditionals     , accept, ignore, norecurse, prune@@ -24,28 +28,46 @@     -- * Boolean logic     , matches, if_, when_, unless_, or_, and_, not_ -    -- * Helper functions+    -- * helper functions     , recurse, test     )     where -import Control.Applicative-import Control.Arrow ((***), first)-import Control.Monad hiding (mapM_, sequence_)-import Control.Monad.Base-import Control.Monad.Catch-import Control.Monad.Morph-import Control.Monad.Reader.Class-import Control.Monad.State.Class-import Control.Monad.Trans-import Control.Monad.Trans.Control-import Control.Monad.Trans.State (StateT(..), withStateT, evalStateT)-import Data.Foldable-import Data.Functor.Identity-import Data.Maybe (isJust)-import Data.Monoid hiding ((<>))-import Data.Semigroup-import Prelude hiding (mapM_, foldr1, sequence_)+import           Control.Applicative+import           Control.Arrow ((***))+import           Control.Monad hiding (mapM_, sequence_)+import           Control.Monad.Base+import           Control.Monad.Catch+import           Control.Monad.Cont.Class as C+import           Control.Monad.Error.Class as E+import           Control.Monad.Fix+import           Control.Monad.Morph as M+import           Control.Monad.Reader.Class as R+import           Control.Monad.State.Class as S+import           Control.Monad.Trans+import           Control.Monad.Trans.Cont (ContT(..))+import           Control.Monad.Trans.Control+import           Control.Monad.Trans.Error (ErrorT(..))+import           Control.Monad.Trans.Except (ExceptT(..))+import           Control.Monad.Trans.Identity (IdentityT(..))+import           Control.Monad.Trans.List (ListT(..))+import           Control.Monad.Trans.Maybe (MaybeT(..))+import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS+import qualified Control.Monad.Trans.RWS.Strict as StrictRWS+import           Control.Monad.Trans.Reader (ReaderT(..))+import           Control.Monad.Trans.State (StateT(..), evalStateT)+import qualified Control.Monad.Trans.State.Lazy as Lazy+import qualified Control.Monad.Trans.State.Strict as Strict+import qualified Control.Monad.Trans.Writer.Lazy as Lazy+import qualified Control.Monad.Trans.Writer.Strict as Strict+import           Control.Monad.Writer.Class+import           Control.Monad.Zip+import           Data.Foldable+import           Data.Functor.Identity+import           Data.Maybe (isJust)+import           Data.Monoid hiding ((<>))+import           Data.Semigroup+import           Prelude hiding (mapM_, foldr1, sequence_)  data Recursor a m r = Stop | Recurse (CondT a m r) | Continue     deriving Functor@@ -161,20 +183,30 @@             x@_ -> return x     {-# INLINEABLE (>>=) #-} -instance Monad m => MonadReader a (CondT a m) where-    ask               = CondT $ gets accept'+instance MonadReader r m => MonadReader r (CondT a m) where+    ask = lift R.ask     {-# INLINE ask #-}-    local f (CondT m) = CondT $ withStateT f m+    local f (CondT m) = CondT $ R.local f m     {-# INLINE local #-}-    reader f          = liftM f ask+    reader = lift . R.reader     {-# INLINE reader #-} -instance Monad m => MonadState a (CondT a m) where-    get     = CondT $ gets accept'+instance MonadWriter w m => MonadWriter w (CondT a m) where+    writer   = lift . writer+    {-# INLINE writer #-}+    tell     = lift . tell+    {-# INLINE tell #-}+    listen m = m >>= lift . listen . return+    {-# INLINE listen #-}+    pass m   = m >>= lift . pass . return+    {-# INLINE pass #-}++instance MonadState s m => MonadState s (CondT a m) where+    get = lift S.get     {-# INLINE get #-}-    put s   = CondT $ liftM accept' $ put s+    put = lift . S.put     {-# INLINE put #-}-    state f = CondT $ state (fmap (first accept') f)+    state = lift . S.state     {-# INLINE state #-}  instance (Monad m, Functor m) => Alternative (CondT a m) where@@ -197,6 +229,10 @@             _ -> g     {-# INLINEABLE mplus #-} +instance MonadError e m => MonadError e (CondT a m) where+    throwError = CondT . throwError+    catchError (CondT m) h = CondT $ m `catchError` \e -> getCondT (h e)+ instance MonadThrow m => MonadThrow (CondT a m) where     throwM = CondT . throwM     {-# INLINE throwM #-}@@ -216,6 +252,7 @@       where q u = CondT . u . getCondT     {-# INLINEABLE uninterruptibleMask #-} + instance MonadBase b m => MonadBase b (CondT a m) where     liftBase m = CondT $ liftM accept' $ liftBase m     {-# INLINE liftBase #-}@@ -252,6 +289,27 @@ instance MFunctor (CondT a) where     hoist nat (CondT m) = CondT $ hoist nat (fmap (hoist nat) `liftM` m)     {-# INLINE hoist #-}++-- This won't work for StateT-like types+-- instance MMonad (CondT a) where+--     embed f m = undefined+--     {-# INLINE embed #-}++instance MonadCont m => MonadCont (CondT a m) where+    callCC f = CondT $ StateT $ \a ->+        callCC $ \k -> flip runStateT a $ getCondT $ f $ \r ->+            CondT $ StateT $ \a' -> k ((Just r, Continue), a')++instance Monad m => MonadZip (CondT a m) where+    mzipWith = liftM2++-- A deficiency of this instance is that recursion uses the same initial 'a'.+instance MonadFix m => MonadFix (CondT a m) where+    mfix f = CondT $ StateT $ \a -> mdo+        ((mb, n), a') <- case mb of+            Nothing -> return ((mb, n), a')+            Just b  -> runStateT (getCondT (f b)) a+        return ((mb, n), a')  runCondT :: Monad m => CondT a m r -> a -> m (Maybe r) runCondT (CondT f) a = fst `liftM` evalStateT f a@@ -272,33 +330,121 @@     recursorToMaybe _ Stop        = Nothing     recursorToMaybe p Continue    = Just p     recursorToMaybe _ (Recurse n) = Just n+{-# INLINEABLE applyCondT #-} -{-# INLINE applyCondT #-}+-- | 'MonadQuery' is a custom version of 'MonadReader', created so that users+-- could still have their own 'MonadReader' accessible within conditionals.+class Monad m => MonadQuery a m | m -> a where+    query :: m a+    queries :: (a -> b) -> m b+    update :: a -> m () +instance Monad m => MonadQuery a (CondT a m) where+    -- | Returns the item currently under consideration.+    query = CondT $ gets accept'+    {-# INLINE query #-}++    -- | Returns the item currently under consideration while applying a+    -- function, in the spirit of 'asks'.+    queries f = CondT $ state (\a -> (accept' (f a), a))+    {-# INLINE queries #-}++    update a = CondT $ liftM accept' $ put a+    {-# INLINE update #-}++instance MonadQuery r m => MonadQuery r (ReaderT r m) where+    query = lift query+    queries = lift . queries+    update = lift . update++instance (MonadQuery r m, Monoid w) => MonadQuery r (LazyRWS.RWST r w s m) where+    query = lift query+    queries = lift . queries+    update = lift . update++instance (MonadQuery r m, Monoid w)+         => MonadQuery r (StrictRWS.RWST r w s m) where+    query = lift query+    queries = lift . queries+    update = lift . update++-- All of these instances need UndecidableInstances, because they do not satisfy+-- the coverage condition.++instance MonadQuery r' m => MonadQuery r' (ContT r m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance (Error e, MonadQuery r m) => MonadQuery r (ErrorT e m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance MonadQuery r m => MonadQuery r (ExceptT e m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance MonadQuery r m => MonadQuery r (IdentityT m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance MonadQuery r m => MonadQuery r (ListT m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance MonadQuery r m => MonadQuery r (MaybeT m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance MonadQuery r m => MonadQuery r (Lazy.StateT s m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance MonadQuery r m => MonadQuery r (Strict.StateT s m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance (Monoid w, MonadQuery r m) => MonadQuery r (Lazy.WriterT w m) where+    query   = lift query+    queries = lift . queries+    update = lift . update++instance (Monoid w, MonadQuery r m) => MonadQuery r (Strict.WriterT w m) where+    query   = lift query+    queries = lift . queries+    update = lift . update+ guardM :: MonadPlus m => m Bool -> m () guardM = (>>= guard) {-# INLINE guardM #-} -guard_ :: (MonadPlus m, MonadReader a m) => (a -> Bool) -> m ()-guard_ f = ask >>= guard . f+guard_ :: (MonadPlus m, MonadQuery a m) => (a -> Bool) -> m ()+guard_ f = query >>= guard . f {-# INLINE guard_ #-} -guardM_ :: (MonadPlus m, MonadReader a m) => (a -> m Bool) -> m ()-guardM_ f = ask >>= guardM . f+guardM_ :: (MonadPlus m, MonadQuery a m) => (a -> m Bool) -> m ()+guardM_ f = query >>= guardM . f {-# INLINE guardM_ #-}  -- | Apply a value-returning predicate. Note that whether or not this return a -- 'Just' value, recursion will be performed in the entry itself, if -- applicable.-apply :: (MonadPlus m, MonadReader a m) => (a -> m (Maybe r)) -> m r-apply = asks >=> (>>= maybe mzero return)+apply :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe r)) -> m r+apply = queries >=> (>>= maybe mzero return) {-# INLINE apply #-}  -- | Consider an element, as 'apply', but returning a mutated form of the -- element. This can be used to apply optimizations to speed future -- conditions.-consider :: (MonadPlus m, MonadState a m) => (a -> m (Maybe (r, a))) -> m r-consider = gets >=> (>>= maybe mzero (\(r, a') -> const r `liftM` put a'))+consider :: (MonadPlus m, MonadQuery a m) => (a -> m (Maybe (r, a))) -> m r+consider = queries >=> (>>= maybe mzero (\(r, a') -> const r `liftM` update a')) {-# INLINE consider #-}  accept :: MonadPlus m => m ()@@ -327,12 +473,12 @@ --   not.  This differs from simply stating the condition in that it itself --   always succeeds. ----- >>> flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hs"))+-- >>> flip runCond "foo.hs" $ matches (guard =<< queries (== "foo.hs")) -- Just True--- >>> flip runCond "foo.hs" $ matches (guard =<< asks (== "foo.hi"))+-- >>> flip runCond "foo.hs" $ matches (guard =<< queries (== "foo.hi")) -- Just False-matches :: (Monad m, Functor m) => CondT a m r -> CondT a m Bool-matches = liftM isJust . optional+matches :: MonadPlus m => m r -> m Bool+matches m = (const True `liftM` m) `mplus` return False {-# INLINE matches #-}  -- | A variant of ifM which branches on whether the condition succeeds or not.@@ -345,10 +491,8 @@ -- Just "Success" -- >>> flip runCond "foo.hs" $ if_ bad (return "Success") (return "Failure") -- Just "Failure"-if_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m s -> CondT a m s-if_ c x y = CondT $ do-    t <- getCondT c-    getCondT $ maybe y (const x) (fst t)+if_ :: MonadPlus m => m r -> m s -> m s -> m s+if_ c x y = matches c >>= \b -> if b then x else y {-# INLINE if_ #-}  -- | 'when_' is just like 'when', except that it executes the body if the@@ -360,7 +504,7 @@ -- Nothing -- >>> flip runCond "foo.hs" $ when_ bad ignore -- Just ()-when_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m ()+when_ :: MonadPlus m => m r -> m s -> m () when_ c x = if_ c (x >> return ()) (return ()) {-# INLINE when_ #-} @@ -373,7 +517,7 @@ -- Nothing -- >>> flip runCond "foo.hs" $ unless_ good ignore -- Just ()-unless_ :: Monad m => CondT a m r -> CondT a m s -> CondT a m ()+unless_ :: MonadPlus m => m r -> m s -> m () unless_ c x = if_ c (return ()) (x >> return ()) {-# INLINE unless_ #-} @@ -386,7 +530,7 @@ -- Just () -- >>> flip runCond "foo.hs" $ or_ [bad] -- Nothing-or_ :: Monad m => [CondT a m r] -> CondT a m r+or_ :: MonadPlus m => [m r] -> m r or_ = Data.Foldable.msum {-# INLINE or_ #-} @@ -399,7 +543,7 @@ -- Nothing -- >>> flip runCond "foo.hs" $ and_ [good] -- Just ()-and_ :: Monad m => [CondT a m r] -> CondT a m ()+and_ :: MonadPlus m => [m r] -> m () and_ = sequence_ {-# INLINE and_ #-} @@ -411,7 +555,7 @@ -- Just "Success" -- >>> flip runCond "foo.hs" $ not_ good >> return "Shouldn't reach here" -- Nothing-not_ :: Monad m => CondT a m r -> CondT a m ()+not_ :: MonadPlus m => m r -> m () not_ c = if_ c ignore accept {-# INLINE not_ #-} 
Pipes/Tree.hs view
@@ -64,7 +64,7 @@ -- -- @ --     let files = winnow (directoryFiles ".") $ do---             path <- ask+--             path <- query --             liftIO $ putStrLn $ "Considering " ++ path --             when (path @`elem@` [".@/@.git", ".@/@dist", ".@/@result"]) --                 prune  -- ignore these, and don't recurse into them
hierarchy.cabal view
@@ -1,5 +1,5 @@ name:          hierarchy-version:       0.1.1+version:       0.2.0 synopsis:      Pipes-based library for predicated traversal of generated trees description:   Pipes-based library for predicated traversal of generated trees homepage:      https://github.com/jwiegley/hierarchy@@ -18,18 +18,19 @@     , Pipes.Tree   ghc-options: -Wall   build-depends:       -      base              >=4.7  && <4.9-    , transformers      >=0.3  && <0.5-    , transformers-base >=0.3  && <0.5-    , exceptions        >=0.8  && <0.9-    , mmorph            >=1.0  && <1.1-    , mtl               >=2.1  && <2.3-    , monad-control     >=1.0  && <1.1-    , semigroups        >=0.16 && <0.17-    , free              >=4.12 && <4.13-    , pipes             >=4.1  && <4.2-    , directory         >=1.2  && <1.3-    , unix              >=2.7  && <2.8+      base                >=4.7  && <4.9+    , transformers        >=0.3  && <0.5+    , transformers-base   >=0.3  && <0.5+    , transformers-compat >=0.3  && <0.5+    , exceptions          >=0.8  && <0.9+    , mmorph              >=1.0  && <1.1+    , mtl                 >=2.1  && <2.3+    , monad-control       >=1.0  && <1.1+    , semigroups          >=0.16 && <0.17+    , free                >=4.12 && <4.13+    , pipes               >=4.1  && <4.2+    , directory           >=1.2  && <1.3+    , unix                >=2.7  && <2.8   -- hs-source-dirs:         default-language:    Haskell2010 
test/Main.hs view
@@ -2,7 +2,6 @@  import Control.Cond import Control.Monad-import Control.Monad.Reader.Class import Data.List import Pipes import Pipes.Prelude (toListM)@@ -19,7 +18,7 @@     let ignored = ["./.git", "./dist", "./result"]      let files = winnow (directoryFiles ".") $ do-            path <- ask+            path <- query             liftIO $ putStrLn $ "Considering " ++ path             when_ (guard_ (`elem` ignored)) $ do                 liftIO $ putStrLn $ "Pruning " ++ path