Skip to content

Commit b1e6fc3

Browse files
Add some combinators to work on monadic predicates
1 parent 3d30857 commit b1e6fc3

1 file changed

Lines changed: 36 additions & 1 deletion

File tree

src/Streamly/Coreutils/FileTest.hs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ module Streamly.Coreutils.FileTest
2727

2828
-- * Boolean Operations
2929
, neg
30+
, negM
3031
, and
32+
, andM
3133
, or
34+
, orM
3235

3336
-- * Running Predicates
3437
, test
38+
, testM
3539
, testFD
3640

3741
-- * Predicates
@@ -93,6 +97,9 @@ instance Monoid (Predicate a) where
9397

9498
#endif
9599

100+
-- $setup
101+
-- >>> import Prelude hiding (or, and)
102+
96103
-- Naming Notes: Named FileTest rather than "Test" to be more explicit and
97104
-- specific. The command can also be named fileTest or testFile.
98105

@@ -109,13 +116,27 @@ or :: FileTest -> FileTest -> FileTest
109116
FileTest (Predicate p) `or` FileTest (Predicate q) =
110117
FileTest (Predicate $ \a -> p a || q a)
111118

119+
-- | Like `or` but for monadic predicates.
120+
--
121+
-- >>> orM t1 t2 = pure or <*> t1 <*> t2
122+
--
123+
orM :: IO FileTest -> IO FileTest -> IO FileTest
124+
orM t1 t2 = pure or <*> t1 <*> t2
125+
112126
-- | A boolean @and@ function for 'FileTest' predicates.
113127
--
114128
-- >>> and = (<>)
115129
--
116130
and :: FileTest -> FileTest -> FileTest
117131
and = (<>)
118132

133+
-- | Like `and` but for monadic predicates.
134+
--
135+
-- >>> andM t1 t2 = pure and <*> t1 <*> t2
136+
--
137+
andM :: IO FileTest -> IO FileTest -> IO FileTest
138+
andM t1 t2 = pure and <*> t1 <*> t2
139+
119140
-- Naming notes: I would prefer to use "not" instead of "neg" but this has to
120141
-- be used unqualified to remain short for common use and prelude "not" is also
121142
-- very common so we do not want to conflict with that.
@@ -135,6 +156,13 @@ and = (<>)
135156
neg :: FileTest -> FileTest
136157
neg (FileTest (Predicate p)) = FileTest (Predicate $ \a -> Prelude.not (p a))
137158

159+
-- | Like `neg` but for monadic predicates.
160+
--
161+
-- >>> negM = fmap neg
162+
--
163+
negM :: IO FileTest -> IO FileTest
164+
negM = fmap neg
165+
138166
-- XXX Use a byte array instead of string filepath.
139167
--
140168
-- | Run a predicate on a 'FilePath'. Returns False if the path does not exist.
@@ -154,8 +182,15 @@ test path (FileTest (Predicate f)) =
154182

155183
eatENOENT e = if isENOENT e then return False else throwIO e
156184

185+
-- | Like 'test' but for a monadic predicate.
186+
--
187+
-- >>> testM path t = test path =<< t
188+
--
189+
testM :: FilePath -> IO FileTest -> IO Bool
190+
testM path t = test path =<< t
191+
157192
-- XXX Use Handle instead
158-
-- | Run a predicate on an 'Fd'.
193+
-- | Like 'test' but uses a file descriptor instead of file path.
159194
testFD :: Fd -> FileTest -> IO Bool
160195
testFD fd (FileTest (Predicate f)) = Files.getFdStatus fd >>= return . f
161196

0 commit comments

Comments
 (0)