Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module defines Predicate
s which you can use to match the arguments of
a method in your execution plan.
Synopsis
- data Predicate a = Predicate {
- showPredicate :: String
- accept :: a -> Bool
- anything :: Predicate a
- eq :: (Show a, Eq a) => a -> Predicate a
- neq :: (Show a, Eq a) => a -> Predicate a
- gt :: (Show a, Ord a) => a -> Predicate a
- geq :: (Show a, Ord a) => a -> Predicate a
- lt :: (Show a, Ord a) => a -> Predicate a
- leq :: (Show a, Ord a) => a -> Predicate a
- just :: Predicate a -> Predicate (Maybe a)
- left :: Predicate a -> Predicate (Either a b)
- right :: Predicate b -> Predicate (Either a b)
- zipP :: Predicate a -> Predicate b -> Predicate (a, b)
- zip3P :: Predicate a -> Predicate b -> Predicate c -> Predicate (a, b, c)
- zip4P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate (a, b, c, d)
- zip5P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate e -> Predicate (a, b, c, d, e)
- andP :: Predicate a -> Predicate a -> Predicate a
- orP :: Predicate a -> Predicate a -> Predicate a
- notP :: Predicate a -> Predicate a
- startsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- endsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- hasSubstr :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- hasSubsequence :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t
- caseInsensitive :: (MonoFunctor t, MonoFunctor a, Element t ~ Char, Element a ~ Char) => (t -> Predicate a) -> t -> Predicate a
- matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- matchesCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- containsCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a
- isEmpty :: MonoFoldable t => Predicate t
- nonEmpty :: MonoFoldable t => Predicate t
- sizeIs :: MonoFoldable t => Predicate Int -> Predicate t
- elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- each :: MonoFoldable t => Predicate (Element t) -> Predicate t
- contains :: MonoFoldable t => Predicate (Element t) -> Predicate t
- containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t
- containsKey :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate t
- containsEntry :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t
- keysAre :: (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t
- entriesAre :: (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t
- approxEq :: (RealFloat a, Show a) => a -> Predicate a
- finite :: RealFloat a => Predicate a
- infinite :: RealFloat a => Predicate a
- nAn :: RealFloat a => Predicate a
- is :: HasCallStack => (a -> Bool) -> Predicate a
- qIs :: HasCallStack => ExpQ -> ExpQ
- with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a
- qWith :: ExpQ -> ExpQ
- qMatch :: PatQ -> ExpQ
- typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b
Documentation
A predicate, which tests values and either accepts or rejects them. This
is similar to a ->
, but also has a Bool
Show
instance to describe what
it is checking.
Predicate
s are used to define which arguments a general matcher should
accept.
Predicate | |
|
anything :: Predicate a Source #
A Predicate
that accepts anything at all.
>>>
accept anything "foo"
True>>>
accept anything undefined
True
eq :: (Show a, Eq a) => a -> Predicate a Source #
A Predicate
that accepts only the given value.
>>>
accept (eq "foo") "foo"
True>>>
accept (eq "foo") "bar"
False
neq :: (Show a, Eq a) => a -> Predicate a Source #
A Predicate
that accepts anything but the given value.
>>>
accept (neq "foo") "foo"
False>>>
accept (neq "foo") "bar"
True
gt :: (Show a, Ord a) => a -> Predicate a Source #
A Predicate
that accepts anything greater than the given value.
>>>
accept (gt 5) 4
False>>>
accept (gt 5) 5
False>>>
accept (gt 5) 6
True
geq :: (Show a, Ord a) => a -> Predicate a Source #
A Predicate
that accepts anything greater than or equal to the given
value.
>>>
accept (geq 5) 4
False>>>
accept (geq 5) 5
True>>>
accept (geq 5) 6
True
lt :: (Show a, Ord a) => a -> Predicate a Source #
A Predicate
that accepts anything less than the given value.
>>>
accept (lt 5) 4
True>>>
accept (lt 5) 5
False>>>
accept (lt 5) 6
False
leq :: (Show a, Ord a) => a -> Predicate a Source #
A Predicate
that accepts anything less than or equal to the given value.
>>>
accept (leq 5) 4
True>>>
accept (leq 5) 5
True>>>
accept (leq 5) 6
False
zip4P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate (a, b, c, d) Source #
zip5P :: Predicate a -> Predicate b -> Predicate c -> Predicate d -> Predicate e -> Predicate (a, b, c, d, e) Source #
andP :: Predicate a -> Predicate a -> Predicate a Source #
A Predicate
that accepts anything accepted by both of its children.
>>>
accept (lt "foo" `andP` gt "bar") "eta"
True>>>
accept (lt "foo" `andP` gt "bar") "quz"
False>>>
accept (lt "foo" `andP` gt "bar") "alpha"
False
orP :: Predicate a -> Predicate a -> Predicate a Source #
A Predicate
that accepts anything accepted by either of its children.
>>>
accept (lt "bar" `orP` gt "foo") "eta"
False>>>
accept (lt "bar" `orP` gt "foo") "quz"
True>>>
accept (lt "bar" `orP` gt "foo") "alpha"
True
startsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t Source #
A Predicate
that accepts sequences that start with the given prefix.
>>>
accept (startsWith "fun") "fungible"
True>>>
accept (startsWith "gib") "fungible"
False
endsWith :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t Source #
A Predicate
that accepts sequences that end with the given suffix.
>>>
accept (endsWith "ow") "crossbow"
True>>>
accept (endsWith "ow") "trebuchet"
False
hasSubstr :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t Source #
A Predicate
that accepts sequences that contain the given (consecutive)
substring.
>>>
accept (hasSubstr "i") "team"
False>>>
accept (hasSubstr "i") "partnership"
True
hasSubsequence :: (Show t, IsSequence t, Eq (Element t)) => t -> Predicate t Source #
A Predicate
that accepts sequences that contain the given (not
necessarily consecutive) subsequence.
>>>
accept (hasSubsequence [1..5]) [1, 2, 3, 4, 5]
True>>>
accept (hasSubsequence [1..5]) [0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0]
True>>>
accept (hasSubsequence [1..5]) [2, 3, 5, 7, 11]
False
caseInsensitive :: (MonoFunctor t, MonoFunctor a, Element t ~ Char, Element a ~ Char) => (t -> Predicate a) -> t -> Predicate a Source #
Transforms a Predicate
on String
s or string-like types to match without
regard to case.
>>>
accept (caseInsensitive startsWith "foo") "FOOTBALL!"
True>>>
accept (caseInsensitive endsWith "ball") "soccer"
False>>>
accept (caseInsensitive eq "time") "TIME"
True>>>
accept (caseInsensitive gt "NOTHING") "everything"
False
matchesRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a Source #
A Predicate
that accepts String
s or string-like values matching a
regular expression. The expression must match the entire argument.
You should not use
, because regular
expression syntax itself is still case-sensitive even when the text you are
matching is not. Instead, use caseInsensitive
matchesRegex
matchesCaseInsensitiveRegex
.
>>>
accept (matchesRegex "x{2,5}y?") "xxxy"
True>>>
accept (matchesRegex "x{2,5}y?") "xyy"
False>>>
accept (matchesRegex "x{2,5}y?") "wxxxyz"
False
matchesCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a Source #
A Predicate
that accepts String
s or string-like values matching a
regular expression in a case-insensitive way. The expression must match the
entire argument.
You should use this instead of
, because
regular expression syntax itself is still case-sensitive even when the text
you are matching is not.caseInsensitive
matchesRegex
>>>
accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XXXY"
True>>>
accept (matchesCaseInsensitiveRegex "x{2,5}y?") "XYY"
False>>>
accept (matchesCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ"
False
containsRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a Source #
A Predicate
that accepts String
s or string-like values containing a
match for a regular expression. The expression need not match the entire
argument.
You should not use
, because regular
expression syntax itself is still case-sensitive even when the text you are
matching is not. Instead, use caseInsensitive
containsRegex
containsCaseInsensitiveRegex
.
>>>
accept (containsRegex "x{2,5}y?") "xxxy"
True>>>
accept (containsRegex "x{2,5}y?") "xyy"
False>>>
accept (containsRegex "x{2,5}y?") "wxxxyz"
True
containsCaseInsensitiveRegex :: (RegexLike Regex a, Eq a) => String -> Predicate a Source #
A Predicate
that accepts String
s or string-like values containing a
match for a regular expression in a case-insensitive way. The expression
need match the entire argument.
You should use this instead of
, because
regular expression syntax itself is still case-sensitive even when the text
you are matching is not.caseInsensitive
containsRegex
>>>
accept (containsCaseInsensitiveRegex "x{2,5}y?") "XXXY"
True>>>
accept (containsCaseInsensitiveRegex "x{2,5}y?") "XYY"
False>>>
accept (containsCaseInsensitiveRegex "x{2,5}y?") "WXXXYZ"
True
isEmpty :: MonoFoldable t => Predicate t Source #
A Predicate
that accepts empty data structures.
>>>
accept isEmpty []
True>>>
accept isEmpty [1, 2, 3]
False>>>
accept isEmpty ""
True>>>
accept isEmpty "gas tank"
False
nonEmpty :: MonoFoldable t => Predicate t Source #
A Predicate
that accepts non-empty data structures.
>>>
accept nonEmpty []
False>>>
accept nonEmpty [1, 2, 3]
True>>>
accept nonEmpty ""
False>>>
accept nonEmpty "gas tank"
True
elemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t Source #
A Predicate
that accepts data structures whose contents each match the
corresponding Predicate
in the given list, in the same order.
>>>
accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4]
True>>>
accept (elemsAre [lt 3, lt 4, lt 5]) [2, 3, 4, 5]
False>>>
accept (elemsAre [lt 3, lt 4, lt 5]) [2, 10, 4]
False
unorderedElemsAre :: MonoFoldable t => [Predicate (Element t)] -> Predicate t Source #
A Predicate
that accepts data structures whose contents each match the
corresponding Predicate
in the given list, in any order.
>>>
accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3]
True>>>
accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [2, 3, 1]
True>>>
accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 2, 3, 4]
False>>>
accept (unorderedElemsAre [eq 1, eq 2, eq 3]) [1, 3]
False
containsAll :: MonoFoldable t => [Predicate (Element t)] -> Predicate t Source #
A Predicate
that accepts data structures which contain an element
satisfying each of the child Predicate
s.
is equivalent to containsAll
[p1, p2, ..., pn]
.contains
p1 `andP
` contains
p2 `andP
` ... `andP
`
contains
pn
>>>
accept (containsAll [eq "foo", eq "bar"]) ["bar", "foo"]
True>>>
accept (containsAll [eq "foo", eq "bar"]) ["foo"]
False>>>
accept (containsAll [eq "foo", eq "bar"]) ["foo", "bar", "qux"]
True
containsOnly :: MonoFoldable t => [Predicate (Element t)] -> Predicate t Source #
A Predicate
that accepts data structures whose elements all satisfy at
least one of the child Predicate
s.
is
equivalent to containsOnly
[p1, p2, ..., pn]
.each
(p1 `orP
` p2 `orP
` ... `orP
` pn)
>>>
accept (containsOnly [eq "foo", eq "bar"]) ["foo", "foo"]
True>>>
accept (containsOnly [eq "foo", eq "bar"]) ["foo", "bar"]
True>>>
accept (containsOnly [eq "foo", eq "bar"]) ["foo", "qux"]
False
containsEntry :: (IsList t, Item t ~ (k, v)) => Predicate k -> Predicate v -> Predicate t Source #
A Predicate
that accepts map-like structures which contain a key/value
pair matched by the given child Predicate
s (one for the key, and one for
the value).
>>>
accept (containsEntry (eq "foo") (gt 10)) [("foo", 12), ("bar", 5)]
True>>>
accept (containsEntry (eq "foo") (gt 10)) [("foo", 5), ("bar", 12)]
False>>>
accept (containsEntry (eq "foo") (gt 10)) [("bar", 12)]
False
keysAre :: (IsList t, Item t ~ (k, v)) => [Predicate k] -> Predicate t Source #
A Predicate
that accepts map-like structures whose keys are exactly those
matched by the given list of Predicate
s, in any order.
>>>
accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("b", 2), ("c", 3)]
True>>>
accept (keysAre [eq "a", eq "b", eq "c"]) [("c", 1), ("b", 2), ("a", 3)]
True>>>
accept (keysAre [eq "a", eq "b", eq "c"]) [("a", 1), ("c", 3)]
False>>>
accept (keysAre [eq "a", eq "b"]) [("a", 1), ("b", 2), ("c", 3)]
False
entriesAre :: (IsList t, Item t ~ (k, v)) => [(Predicate k, Predicate v)] -> Predicate t Source #
A Predicate
that accepts map-like structures whose entries are exactly
those matched by the given list of Predicate
pairs, in any order.
>>>
accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4)]
True>>>
accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(3, 4), (1, 2)]
True>>>
accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 4), (3, 2)]
False>>>
accept (entriesAre [(eq 1, eq 2), (eq 3, eq 4)]) [(1, 2), (3, 4), (5, 6)]
False
approxEq :: (RealFloat a, Show a) => a -> Predicate a Source #
A Predicate
that accepts values of RealFloat
types that are close to
the given number. The expected precision is scaled based on the target
value, so that reasonable rounding error is accepted but grossly inaccurate
results are not.
The following naive use of eq
fails due to rounding:
>>>
accept (eq 1.0) (sum (replicate 100 0.01))
False
The solution is to use approxEq
, which accounts for rounding error.
However, approxEq
doesn't accept results that are far enough off that they
likely arise from incorrect calculations instead of rounding error.
>>>
accept (approxEq 1.0) (sum (replicate 100 0.01))
True>>>
accept (approxEq 1.0) (sum (replicate 100 0.009999))
False
qIs :: HasCallStack => ExpQ -> ExpQ Source #
A Template Haskell splice that acts like is
, but receives a quoted
expression at compile time and has a more helpful description for error
messages.
>>>
accept $(qIs [| even |]) 3
False>>>
accept $(qIs [| even |]) 4
True
>>>
show $(qIs [| even |])
"even"
with :: HasCallStack => (a -> b) -> Predicate b -> Predicate a Source #
A combinator to lift a Predicate
to work on a property or computed value
of the original value.
>>>
accept (with abs (gt 5)) (-6)
True>>>
accept (with abs (gt 5)) (-5)
False>>>
accept (with reverse (eq "olleh")) "hello"
True>>>
accept (with reverse (eq "olleh")) "goodbye"
False
qWith :: ExpQ -> ExpQ Source #
A Template Haskell splice that acts like is
, but receives a quoted typed
expression at compile time and has a more helpful description for error
messages.
>>>
accept ($(qWith [| abs |]) (gt 5)) (-6)
True>>>
accept ($(qWith [| abs |]) (gt 5)) (-5)
False>>>
accept ($(qWith [| reverse |]) (eq "olleh")) "hello"
True>>>
accept ($(qWith [| reverse |]) (eq "olleh")) "goodbye"
False
>>>
show ($(qWith [| abs |]) (gt 5))
"abs: > 5"
qMatch :: PatQ -> ExpQ Source #
A Template Haskell splice that turns a quoted pattern into a predicate that accepts values that match the pattern.
>>>
accept $(qMatch [p| Just (Left _) |]) Nothing
False>>>
accept $(qMatch [p| Just (Left _) |]) (Just (Left 5))
True>>>
accept $(qMatch [p| Just (Left _) |]) (Just (Right 5))
False
>>>
show $(qMatch [p| Just (Left _) |])
"Just (Left _)"
typed :: forall a b. (Typeable a, Typeable b) => Predicate a -> Predicate b Source #
Converts a Predicate
to a new type. Typically used with visible type
application, as in the examples below.
>>>
accept (typed @String anything) "foo"
True>>>
accept (typed @String (sizeIs (gt 5))) "foo"
False>>>
accept (typed @String anything) (42 :: Int)
False