Skip to content

Commit d5f58e6

Browse files
Add/rename boolean operations for FileTest
1 parent dddee00 commit d5f58e6

1 file changed

Lines changed: 34 additions & 9 deletions

File tree

src/Streamly/Coreutils/FileTest.hs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ module Streamly.Coreutils.FileTest
2424
(
2525
-- * File Test Predicate Type
2626
FileTest
27-
, pOr
27+
28+
-- * Boolean Operations
29+
, neg
30+
, and
31+
, or
2832

2933
-- * Running Predicates
3034
, test
@@ -71,6 +75,7 @@ import GHC.IO.Exception (IOException(..), IOErrorType(..))
7175
import System.Posix.Types (Fd)
7276
import System.Posix.Files (FileStatus)
7377
import qualified System.Posix.Files as Files
78+
import Prelude hiding (and, or)
7479

7580
#if MIN_VERSION_base(4,12,0)
7681
import Data.Functor.Contravariant (Predicate(..))
@@ -98,18 +103,38 @@ instance Monoid (Predicate a) where
98103
--
99104
newtype FileTest = FileTest (Predicate FileStatus) deriving (Semigroup, Monoid)
100105

101-
-- Though || can be expressed in terms of not and && but || is really
102-
-- convienient. If we had a type class for <|> we could have defined an
103-
-- instance of that for Predicate. Or maybe we can have a typeclass for Bool
104-
-- like we have for Num, defining "and", "or" and "not".
105-
106106
-- | A boolean @or@ function for 'FileTest' predicates.
107107
--
108-
-- For boolean and operation use the Semigroup instance.
109-
pOr :: FileTest -> FileTest -> FileTest
110-
FileTest (Predicate p) `pOr` FileTest (Predicate q) =
108+
or :: FileTest -> FileTest -> FileTest
109+
FileTest (Predicate p) `or` FileTest (Predicate q) =
111110
FileTest (Predicate $ \a -> p a || q a)
112111

112+
-- | A boolean @and@ function for 'FileTest' predicates.
113+
--
114+
-- >>> and = (<>)
115+
--
116+
and :: FileTest -> FileTest -> FileTest
117+
and = (<>)
118+
119+
-- Naming notes: I would prefer to use "not" instead of "neg" but this has to
120+
-- be used unqualified to remain short for common use and prelude "not" is also
121+
-- very common so we do not want to conflict with that.
122+
--
123+
-- XXX Should we have an IsBool type class in Data.Bool so that the boolean
124+
-- operations (&&, ||, not) can be overloaded.
125+
--
126+
-- class IsBool a where
127+
-- not :: a -> a
128+
-- (&&) :: a -> a -> a -- and
129+
-- (||) :: a -> a -> a -- or
130+
131+
-- | A boolean @not@ function for 'FileTest' predicates.
132+
--
133+
-- >>> and = (<>)
134+
--
135+
neg :: FileTest -> FileTest
136+
neg (FileTest (Predicate p)) = FileTest (Predicate $ \a -> Prelude.not (p a))
137+
113138
-- XXX Use a byte array instead of string filepath.
114139
--
115140
-- | Run a predicate on a 'FilePath'. Returns False if the path does not exist.

0 commit comments

Comments
 (0)