From b1e6fc37f0e898c54378129750d3ccc1c034f611 Mon Sep 17 00:00:00 2001 From: Harendra Kumar Date: Mon, 13 Jun 2022 17:58:36 +0530 Subject: [PATCH] Add some combinators to work on monadic predicates --- src/Streamly/Coreutils/FileTest.hs | 37 +++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Streamly/Coreutils/FileTest.hs b/src/Streamly/Coreutils/FileTest.hs index 609d80c..58b3a1c 100644 --- a/src/Streamly/Coreutils/FileTest.hs +++ b/src/Streamly/Coreutils/FileTest.hs @@ -27,11 +27,15 @@ module Streamly.Coreutils.FileTest -- * Boolean Operations , neg + , negM , and + , andM , or + , orM -- * Running Predicates , test + , testM , testFD -- * Predicates @@ -93,6 +97,9 @@ instance Monoid (Predicate a) where #endif +-- $setup +-- >>> import Prelude hiding (or, and) + -- Naming Notes: Named FileTest rather than "Test" to be more explicit and -- specific. The command can also be named fileTest or testFile. @@ -109,6 +116,13 @@ or :: FileTest -> FileTest -> FileTest FileTest (Predicate p) `or` FileTest (Predicate q) = FileTest (Predicate $ \a -> p a || q a) +-- | Like `or` but for monadic predicates. +-- +-- >>> orM t1 t2 = pure or <*> t1 <*> t2 +-- +orM :: IO FileTest -> IO FileTest -> IO FileTest +orM t1 t2 = pure or <*> t1 <*> t2 + -- | A boolean @and@ function for 'FileTest' predicates. -- -- >>> and = (<>) @@ -116,6 +130,13 @@ FileTest (Predicate p) `or` FileTest (Predicate q) = and :: FileTest -> FileTest -> FileTest and = (<>) +-- | Like `and` but for monadic predicates. +-- +-- >>> andM t1 t2 = pure and <*> t1 <*> t2 +-- +andM :: IO FileTest -> IO FileTest -> IO FileTest +andM t1 t2 = pure and <*> t1 <*> t2 + -- Naming notes: I would prefer to use "not" instead of "neg" but this has to -- be used unqualified to remain short for common use and prelude "not" is also -- very common so we do not want to conflict with that. @@ -135,6 +156,13 @@ and = (<>) neg :: FileTest -> FileTest neg (FileTest (Predicate p)) = FileTest (Predicate $ \a -> Prelude.not (p a)) +-- | Like `neg` but for monadic predicates. +-- +-- >>> negM = fmap neg +-- +negM :: IO FileTest -> IO FileTest +negM = fmap neg + -- XXX Use a byte array instead of string filepath. -- -- | Run a predicate on a 'FilePath'. Returns False if the path does not exist. @@ -154,8 +182,15 @@ test path (FileTest (Predicate f)) = eatENOENT e = if isENOENT e then return False else throwIO e +-- | Like 'test' but for a monadic predicate. +-- +-- >>> testM path t = test path =<< t +-- +testM :: FilePath -> IO FileTest -> IO Bool +testM path t = test path =<< t + -- XXX Use Handle instead --- | Run a predicate on an 'Fd'. +-- | Like 'test' but uses a file descriptor instead of file path. testFD :: Fd -> FileTest -> IO Bool testFD fd (FileTest (Predicate f)) = Files.getFdStatus fd >>= return . f