@@ -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(..))
7175import System.Posix.Types (Fd )
7276import System.Posix.Files (FileStatus )
7377import qualified System.Posix.Files as Files
78+ import Prelude hiding (and , or )
7479
7580#if MIN_VERSION_base(4,12,0)
7681import Data.Functor.Contravariant (Predicate (.. ))
@@ -98,18 +103,38 @@ instance Monoid (Predicate a) where
98103--
99104newtype 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