-- vim:fdm=marker:foldtext=foldtext()---------------------------------------------------------------------- |-- Module : Test.SmallCheck.Property-- Copyright : (c) Colin Runciman et al.-- License : BSD3-- Maintainer: Roman Cheplyaka <roma@ro-che.info>---- Properties and tools to construct them.--------------------------------------------------------------------{-# LANGUAGE CPP #-}{-# LANGUAGE DeriveDataTypeable #-}{-# LANGUAGE FlexibleInstances #-}{-# LANGUAGE MultiParamTypeClasses #-}{-# LANGUAGE NoImplicitPrelude #-}{-# LANGUAGE ScopedTypeVariables #-}{-# LANGUAGE TypeFamilies #-}{-# LANGUAGE TypeOperators #-}-- Are we using new, polykinded and derivable Typeable yet?
#define NEWTYPEABLE MIN_VERSION_base(4,7,0)

#if NEWTYPEABLE
{-# LANGUAGE Safe #-}
#else
-- Trustworthy is needed because of the hand-written Typeable instance
#if __GLASGOW_HASKELL__ >= 704
{-# LANGUAGE Trustworthy #-}
#endif
#endif
moduleTest.SmallCheck.Property(-- * ConstructorsforAll ,exists ,existsUnique ,over ,(==>) ,monadic ,changeDepth ,changeDepth1 ,-- * Property's entrailsProperty ,PropertySuccess (..),PropertyFailure (..),runProperty ,TestQuality (..),Argument ,Reason ,Depth ,Testable (..),)whereimportControl.Applicative(pure,(<$>),(<$))importControl.Arrow(first)importControl.Monad(Monad,liftM,mzero,return,(=<<),(>>=))importControl.Monad.Logic(MonadLogic,runLogicT,ifte,once,msplit,lnot)importControl.Monad.Reader(Reader,runReader,lift,ask,local,reader)importData.Bool(Bool,otherwise)importData.Either(Either,either)importData.Eq(Eq)importData.Function(($),flip,(.),const,id)importData.Functor(fmap)importData.Int(Int)importData.Maybe(Maybe(Nothing,Just))importData.Ord(Ord,(<=))importData.Typeable(Typeable)importPrelude(Enum,(-))importTest.SmallCheck.Property.Result importTest.SmallCheck.Series importTest.SmallCheck.SeriesMonad importText.Show(Show,show)
#if MIN_VERSION_base(4,17,0)
importData.Type.Equality(type(~))
#endif

#if !NEWTYPEABLE
importData.Typeable(Typeable1,mkTyConApp,typeOf)importPrelude(undefined)
#if MIN_VERSION_base(4,4,0)
importData.Typeable(mkTyCon3)
#else
importData.Typeable(mkTyCon)
#endif
#endif
-------------------------------- Property-related types--------------------------------{{{-- | The type of properties over the monad @m@.---- @since 1.0newtypeProperty m =Property {forall (m :: * -> *).
Property m -> Reader (Env m) (PropertySeries m)
unProperty ::Reader(Env m )(PropertySeries m )}
#if NEWTYPEABLE
derivingTypeable
#endif
dataPropertySeries m =PropertySeries {forall (m :: * -> *). PropertySeries m -> Series m PropertySuccess
searchExamples ::Series m PropertySuccess ,forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples ::Series m PropertyFailure ,forall (m :: * -> *).
PropertySeries m -> Series m (Property m, [Argument])
searchClosest ::Series m (Property m ,[Argument ])}dataEnv m =Env {forall (m :: * -> *). Env m -> Quantification
quantification ::Quantification ,forall (m :: * -> *). Env m -> TestQuality -> m ()
testHook ::TestQuality ->m ()}dataQuantification =Forall |Exists |ExistsUnique -- | @since 1.0dataTestQuality =GoodTest |BadTest deriving(TestQuality -> TestQuality -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TestQuality -> TestQuality -> Bool
$c/= :: TestQuality -> TestQuality -> Bool
== :: TestQuality -> TestQuality -> Bool
$c== :: TestQuality -> TestQuality -> Bool
Eq,Eq TestQuality
TestQuality -> TestQuality -> Bool
TestQuality -> TestQuality -> Ordering
TestQuality -> TestQuality -> TestQuality
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TestQuality -> TestQuality -> TestQuality
$cmin :: TestQuality -> TestQuality -> TestQuality
max :: TestQuality -> TestQuality -> TestQuality
$cmax :: TestQuality -> TestQuality -> TestQuality
>= :: TestQuality -> TestQuality -> Bool
$c>= :: TestQuality -> TestQuality -> Bool
> :: TestQuality -> TestQuality -> Bool
$c> :: TestQuality -> TestQuality -> Bool
<= :: TestQuality -> TestQuality -> Bool
$c<= :: TestQuality -> TestQuality -> Bool
< :: TestQuality -> TestQuality -> Bool
$c< :: TestQuality -> TestQuality -> Bool
compare :: TestQuality -> TestQuality -> Ordering
$ccompare :: TestQuality -> TestQuality -> Ordering
Ord,Int -> TestQuality
TestQuality -> Int
TestQuality -> [TestQuality]
TestQuality -> TestQuality
TestQuality -> TestQuality -> [TestQuality]
TestQuality -> TestQuality -> TestQuality -> [TestQuality]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: TestQuality -> TestQuality -> TestQuality -> [TestQuality]
$cenumFromThenTo :: TestQuality -> TestQuality -> TestQuality -> [TestQuality]
enumFromTo :: TestQuality -> TestQuality -> [TestQuality]
$cenumFromTo :: TestQuality -> TestQuality -> [TestQuality]
enumFromThen :: TestQuality -> TestQuality -> [TestQuality]
$cenumFromThen :: TestQuality -> TestQuality -> [TestQuality]
enumFrom :: TestQuality -> [TestQuality]
$cenumFrom :: TestQuality -> [TestQuality]
fromEnum :: TestQuality -> Int
$cfromEnum :: TestQuality -> Int
toEnum :: Int -> TestQuality
$ctoEnum :: Int -> TestQuality
pred :: TestQuality -> TestQuality
$cpred :: TestQuality -> TestQuality
succ :: TestQuality -> TestQuality
$csucc :: TestQuality -> TestQuality
Enum,Int -> TestQuality -> ShowS
[TestQuality] -> ShowS
TestQuality -> Argument
forall a.
(Int -> a -> ShowS) -> (a -> Argument) -> ([a] -> ShowS) -> Show a
showList :: [TestQuality] -> ShowS
$cshowList :: [TestQuality] -> ShowS
show :: TestQuality -> Argument
$cshow :: TestQuality -> Argument
showsPrec :: Int -> TestQuality -> ShowS
$cshowsPrec :: Int -> TestQuality -> ShowS
Show)
#if !NEWTYPEABLE
-- Typeable here is not polykinded yet, and also GHC doesn't know how to-- derive this.instanceTypeable1m=>Typeable(Propertym)wheretypeOf_=mkTyConApp
#if MIN_VERSION_base(4,4,0)
(mkTyCon3"smallcheck""Test.SmallCheck.Property""Property")
#else
(mkTyCon"smallcheck Test.SmallCheck.Property Property")
#endif
[typeOf(undefined::m())]
#endif
-- }}}-------------------------------------- Property runners and constructors--------------------------------------{{{unProp ::Env t ->Property t ->PropertySeries t unProp :: forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env t
q (Property Reader (Env t) (PropertySeries t)
p )=forall r a. Reader r a -> r -> a
runReaderReader (Env t) (PropertySeries t)
p Env t
q runProperty ::Monadm =>Depth ->(TestQuality ->m ())->Property m ->m (MaybePropertyFailure )runProperty :: forall (m :: * -> *).
Monad m =>
Int
-> (TestQuality -> m ()) -> Property m -> m (Maybe PropertyFailure)
runProperty Int
depth TestQuality -> m ()
hook Property m
prop =(\LogicT m PropertyFailure
l ->forall (m :: * -> *) a r.
LogicT m a -> (a -> m r -> m r) -> m r -> m r
runLogicTLogicT m PropertyFailure
l (\PropertyFailure
x m (Maybe PropertyFailure)
_->forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$forall a. a -> Maybe a
JustPropertyFailure
x )(forall (m :: * -> *) a. Monad m => a -> m a
returnforall a. Maybe a
Nothing))forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Int -> Series m a -> LogicT m a
runSeries Int
depth forall a b. (a -> b) -> a -> b
$forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples forall a b. (a -> b) -> a -> b
$forall a b c. (a -> b -> c) -> b -> a -> c
flipforall r a. Reader r a -> r -> a
runReader(forall (m :: * -> *).
Quantification -> (TestQuality -> m ()) -> Env m
Env Quantification
Forall TestQuality -> m ()
hook )forall a b. (a -> b) -> a -> b
$forall (m :: * -> *).
Property m -> Reader (Env m) (PropertySeries m)
unProperty Property m
prop atomicProperty ::Series m PropertySuccess ->Series m PropertyFailure ->PropertySeries m atomicProperty :: forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure -> PropertySeries m
atomicProperty Series m PropertySuccess
s Series m PropertyFailure
f =letprop :: PropertySeries m
prop =forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure
-> Series m (Property m, [Argument])
-> PropertySeries m
PropertySeries Series m PropertySuccess
s Series m PropertyFailure
f (forall (f :: * -> *) a. Applicative f => a -> f a
pure(forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall (f :: * -> *) a. Applicative f => a -> f a
purePropertySeries m
prop ,[]))inPropertySeries m
prop makeAtomic ::Property m ->Property m makeAtomic :: forall (m :: * -> *). Property m -> Property m
makeAtomic (Property Reader (Env m) (PropertySeries m)
prop )=forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall a b c. (a -> b -> c) -> b -> a -> c
flipforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmapReader (Env m) (PropertySeries m)
prop forall a b. (a -> b) -> a -> b
$\PropertySeries m
ps ->forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure -> PropertySeries m
atomicProperty (forall (m :: * -> *). PropertySeries m -> Series m PropertySuccess
searchExamples PropertySeries m
ps )(forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples PropertySeries m
ps )-- | @'over' s $ \\x -> p x@ makes @x@ range over the 'Series' @s@ (by-- default, all variables range over the 'series' for their types).---- Note that, unlike the quantification operators, this affects only the-- variable following the operator and not subsequent variables.---- 'over' does not affect the quantification context.---- @since 1.0over ::(Showa ,Testable m b )=>Series m a ->(a ->b )->Property m over :: forall a (m :: * -> *) b.
(Show a, Testable m b) =>
Series m a -> (a -> b) -> Property m
over =forall a (m :: * -> *) b.
(Show a, Testable m b) =>
Series m a -> (a -> b) -> Property m
testFunction -- | Execute a monadic test.---- @since 1.0monadic ::Testable m a =>m a ->Property m monadic :: forall (m :: * -> *) a. Testable m a => m a -> Property m
monadic m a
a =forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
readerforall a b. (a -> b) -> a -> b
$\Env m
env ->letpair :: Series m (PropertySeries m)
pair =forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (m :: * -> *) a. Testable m a => a -> Property m
freshContext forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
liftm a
a inforall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure -> PropertySeries m
atomicProperty (forall (m :: * -> *). PropertySeries m -> Series m PropertySuccess
searchExamples forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<Series m (PropertySeries m)
pair )(forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<Series m (PropertySeries m)
pair )-- }}}--------------------------------- Testable class and instances--------------------------------- {{{-- | Class of tests that can be run in a monad. For pure tests, it is-- recommended to keep their types polymorphic in @m@ rather than-- specialising it to 'Data.Functor.Identity'.---- @since 1.0classMonadm =>Testable m a where-- | @since 1.0test ::a ->Property m instanceMonadm =>Testable m Boolwheretest :: Bool -> Property m
test Bool
b =forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
readerforall a b. (a -> b) -> a -> b
$\Env m
env ->letsuccess :: Series m PropertySuccess
success =doforall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
liftforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). Env m -> TestQuality -> m ()
testHook Env m
env TestQuality
GoodTest ifBool
b thenforall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$Maybe Argument -> PropertySuccess
PropertyTrue forall a. Maybe a
Nothingelseforall (m :: * -> *) a. MonadPlus m => m a
mzerofailure :: Series m PropertyFailure
failure =Maybe Argument -> PropertyFailure
PropertyFalse forall a. Maybe a
Nothingforall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$forall (m :: * -> *) a. MonadLogic m => m a -> m ()
lnotSeries m PropertySuccess
success inforall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure -> PropertySeries m
atomicProperty Series m PropertySuccess
success Series m PropertyFailure
failure -- | Works like the 'Data.Bool.Bool' instance, but includes an explanation of the result.---- 'Data.Either.Left' and 'Data.Either.Right' correspond to test failure and success-- respectively.---- @since 1.1instanceMonadm =>Testable m (EitherReason Reason )wheretest :: Either Argument Argument -> Property m
test Either Argument Argument
r =forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
readerforall a b. (a -> b) -> a -> b
$\Env m
env ->letsuccess :: Series m PropertySuccess
success =doforall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
liftforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). Env m -> TestQuality -> m ()
testHook Env m
env TestQuality
GoodTest forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either(forall a b. a -> b -> a
constforall (m :: * -> *) a. MonadPlus m => m a
mzero)(forall (f :: * -> *) a. Applicative f => a -> f a
pureforall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe Argument -> PropertySuccess
PropertyTrue forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. a -> Maybe a
Just)Either Argument Argument
r failure :: Series m PropertyFailure
failure =doforall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
liftforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). Env m -> TestQuality -> m ()
testHook Env m
env TestQuality
GoodTest forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either(forall (f :: * -> *) a. Applicative f => a -> f a
pureforall b c a. (b -> c) -> (a -> b) -> a -> c
.Maybe Argument -> PropertyFailure
PropertyFalse forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a. a -> Maybe a
Just)(forall a b. a -> b -> a
constforall (m :: * -> *) a. MonadPlus m => m a
mzero)Either Argument Argument
r inforall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure -> PropertySeries m
atomicProperty Series m PropertySuccess
success Series m PropertyFailure
failure instance(Serial m a ,Showa ,Testable m b )=>Testable m (a ->b )wheretest :: (a -> b) -> Property m
test =forall a (m :: * -> *) b.
(Show a, Testable m b) =>
Series m a -> (a -> b) -> Property m
testFunction forall (m :: * -> *) a. Serial m a => Series m a
series instance(Monadm ,m ~n )=>Testable n (Property m )wheretest :: Property m -> Property n
test =forall a. a -> a
idtestFunction ::(Showa ,Testable m b )=>Series m a ->(a ->b )->Property m testFunction :: forall a (m :: * -> *) b.
(Show a, Testable m b) =>
Series m a -> (a -> b) -> Property m
testFunction Series m a
s a -> b
f =forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
readerforall a b. (a -> b) -> a -> b
$\Env m
env ->letclosest :: Series m (Property m, [Argument])
closest =doa
x <-Series m a
s (Property m
p ,[Argument]
args )<-forall (m :: * -> *).
PropertySeries m -> Series m (Property m, [Argument])
searchClosest forall a b. (a -> b) -> a -> b
$forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Testable m a => a -> Property m
test forall a b. (a -> b) -> a -> b
$a -> b
f a
x forall (m :: * -> *) a. Monad m => a -> m a
return(Property m
p ,forall a. Show a => a -> Argument
showa
x forall a. a -> [a] -> [a]
:[Argument]
args )incaseforall (m :: * -> *). Env m -> Quantification
quantification Env m
env ofQuantification
Forall ->forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure
-> Series m (Property m, [Argument])
-> PropertySeries m
PropertySeries Series m PropertySuccess
success Series m PropertyFailure
failure Series m (Property m, [Argument])
closest -- {{{wherefailure :: Series m PropertyFailure
failure =doa
x <-Series m a
s PropertyFailure
failure <-forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples forall a b. (a -> b) -> a -> b
$forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Testable m a => a -> Property m
test forall a b. (a -> b) -> a -> b
$a -> b
f a
x letarg :: Argument
arg =forall a. Show a => a -> Argument
showa
x forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$casePropertyFailure
failure ofCounterExample [Argument]
args PropertyFailure
etc ->[Argument] -> PropertyFailure -> PropertyFailure
CounterExample (Argument
arg forall a. a -> [a] -> [a]
:[Argument]
args )PropertyFailure
etc PropertyFailure
_->[Argument] -> PropertyFailure -> PropertyFailure
CounterExample [Argument
arg ]PropertyFailure
failure success :: Series m PropertySuccess
success =Maybe Argument -> PropertySuccess
PropertyTrue forall a. Maybe a
Nothingforall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$forall (m :: * -> *) a. MonadLogic m => m a -> m ()
lnotSeries m PropertyFailure
failure -- }}}Quantification
Exists ->forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure
-> Series m (Property m, [Argument])
-> PropertySeries m
PropertySeries Series m PropertySuccess
success Series m PropertyFailure
failure Series m (Property m, [Argument])
closest -- {{{wheresuccess :: Series m PropertySuccess
success =doa
x <-Series m a
s PropertySuccess
s <-forall (m :: * -> *). PropertySeries m -> Series m PropertySuccess
searchExamples forall a b. (a -> b) -> a -> b
$forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Testable m a => a -> Property m
test forall a b. (a -> b) -> a -> b
$a -> b
f a
x letarg :: Argument
arg =forall a. Show a => a -> Argument
showa
x forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$casePropertySuccess
s ofExist [Argument]
args PropertySuccess
etc ->[Argument] -> PropertySuccess -> PropertySuccess
Exist (Argument
arg forall a. a -> [a] -> [a]
:[Argument]
args )PropertySuccess
etc PropertySuccess
_->[Argument] -> PropertySuccess -> PropertySuccess
Exist [Argument
arg ]PropertySuccess
s failure :: Series m PropertyFailure
failure =PropertyFailure
NotExist forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$forall (m :: * -> *) a. MonadLogic m => m a -> m ()
lnotSeries m PropertySuccess
success -- }}}Quantification
ExistsUnique ->forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure
-> Series m (Property m, [Argument])
-> PropertySeries m
PropertySeries Series m PropertySuccess
success Series m PropertyFailure
failure Series m (Property m, [Argument])
closest -- {{{wheresearch :: Series m [([Argument], PropertySuccess)]
search =forall (m :: * -> *) a. MonadLogic m => Int -> m a -> m [a]
atMost Int
2forall a b. (a -> b) -> a -> b
$do(Property m
prop ,[Argument]
args )<-Series m (Property m, [Argument])
closest PropertySuccess
ex <-forall (m :: * -> *) a. MonadLogic m => m a -> m a
onceforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). PropertySeries m -> Series m PropertySuccess
searchExamples forall a b. (a -> b) -> a -> b
$forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Testable m a => a -> Property m
test Property m
prop forall (m :: * -> *) a. Monad m => a -> m a
return([Argument]
args ,PropertySuccess
ex )success :: Series m PropertySuccess
success =Series m [([Argument], PropertySuccess)]
search forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=\[([Argument], PropertySuccess)]
examples ->case[([Argument], PropertySuccess)]
examples of[([Argument]
x ,PropertySuccess
s )]->forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$[Argument] -> PropertySuccess -> PropertySuccess
ExistUnique [Argument]
x PropertySuccess
s [([Argument], PropertySuccess)]
_->forall (m :: * -> *) a. MonadPlus m => m a
mzerofailure :: Series m PropertyFailure
failure =Series m [([Argument], PropertySuccess)]
search forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=\[([Argument], PropertySuccess)]
examples ->case[([Argument], PropertySuccess)]
examples of[]->forall (m :: * -> *) a. Monad m => a -> m a
returnPropertyFailure
NotExist ([Argument]
x1 ,PropertySuccess
s1 ):([Argument]
x2 ,PropertySuccess
s2 ):[([Argument], PropertySuccess)]
_->forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$[Argument]
-> PropertySuccess
-> [Argument]
-> PropertySuccess
-> PropertyFailure
AtLeastTwo [Argument]
x1 PropertySuccess
s1 [Argument]
x2 PropertySuccess
s2 [([Argument], PropertySuccess)]
_->forall (m :: * -> *) a. MonadPlus m => m a
mzero-- }}}atMost ::MonadLogicm =>Int->m a ->m [a ]atMost :: forall (m :: * -> *) a. MonadLogic m => Int -> m a -> m [a]
atMost Int
n m a
m |Int
n forall a. Ord a => a -> a -> Bool
<=Int
0=forall (m :: * -> *) a. Monad m => a -> m a
return[]|Bool
otherwise=doMaybe (a, m a)
m' <-forall (m :: * -> *) a. MonadLogic m => m a -> m (Maybe (a, m a))
msplitm a
m caseMaybe (a, m a)
m' ofMaybe (a, m a)
Nothing->forall (m :: * -> *) a. Monad m => a -> m a
return[]Just(a
x ,m a
rest )->(a
x forall a. a -> [a] -> [a]
:)forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM`forall (m :: * -> *) a. MonadLogic m => Int -> m a -> m [a]
atMost (Int
n forall a. Num a => a -> a -> a
-Int
1)m a
rest -- }}}-------------------------------- Test constructors-------------------------------- {{{quantify ::Quantification ->Property m ->Property m quantify :: forall (m :: * -> *). Quantification -> Property m -> Property m
quantify Quantification
q (Property Reader (Env m) (PropertySeries m)
a )=forall (m :: * -> *). Property m -> Property m
makeAtomic forall a b. (a -> b) -> a -> b
$forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local(\Env m
env ->Env m
env {quantification :: Quantification
quantification =Quantification
q })Reader (Env m) (PropertySeries m)
a freshContext ::Testable m a =>a ->Property m freshContext :: forall (m :: * -> *) a. Testable m a => a -> Property m
freshContext =forall (m :: * -> *) a. Testable m a => a -> Property m
forAll -- | Set the universal quantification context.---- @since 1.0forAll ::Testable m a =>a ->Property m forAll :: forall (m :: * -> *) a. Testable m a => a -> Property m
forAll =forall (m :: * -> *). Quantification -> Property m -> Property m
quantify Quantification
Forall forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (m :: * -> *) a. Testable m a => a -> Property m
test -- | Set the existential quantification context.---- @since 1.0exists ::Testable m a =>a ->Property m exists :: forall (m :: * -> *) a. Testable m a => a -> Property m
exists =forall (m :: * -> *). Quantification -> Property m -> Property m
quantify Quantification
Exists forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (m :: * -> *) a. Testable m a => a -> Property m
test -- | Set the uniqueness quantification context.---- Bear in mind that \( \exists! x, y\colon p,円 x ,円 y \)-- is not the same as \( \exists! x \colon \exists! y \colon p ,円 x ,円 y \).---- For example, \( \exists! x \colon \exists! y \colon |x| = |y| \)-- is true (it holds only when \(x=y=0\)),-- but \( \exists! x, y \colon |x| = |y| \) is false-- (there are many such pairs).---- As is customary in mathematics,-- @'existsUnique' $ \\x y -> p x y@ is equivalent to-- @'existsUnique' $ \\(x, y) -> p x y@ and not to-- @'existsUnique' $ \\x -> 'existsUnique' $ \\y -> p x y@-- (the latter, of course, may be explicitly written when desired).---- That is, all the variables affected by the same uniqueness context are-- quantified simultaneously as a tuple.---- @since 1.0existsUnique ::Testable m a =>a ->Property m existsUnique :: forall (m :: * -> *) a. Testable m a => a -> Property m
existsUnique =forall (m :: * -> *). Quantification -> Property m -> Property m
quantify Quantification
ExistsUnique forall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (m :: * -> *) a. Testable m a => a -> Property m
test -- | The '==>' operator can be used to express a restricting condition-- under which a property should hold. It corresponds to implication in the-- classical logic.---- Note that '==>' resets the quantification context for its operands to-- the default (universal).---- @since 1.0infixr0==> (==>) ::(Testable m c ,Testable m a )=>c ->a ->Property m c
cond ==> :: forall (m :: * -> *) c a.
(Testable m c, Testable m a) =>
c -> a -> Property m
==> a
prop =forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property forall a b. (a -> b) -> a -> b
$doEnv m
env <-forall r (m :: * -> *). MonadReader r m => m r
askletcounterExample :: Series m PropertyFailure
counterExample =forall (m :: * -> *) a. MonadLogic m => m a -> m a
onceforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples forall a b. (a -> b) -> a -> b
$forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env' forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Testable m a => a -> Property m
freshContext c
cond -- NB: we do not invoke the test hook in the antecedentwhereenv' :: Env m
env' =Env m
env {testHook :: TestQuality -> m ()
testHook =forall a b. a -> b -> a
constforall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Monad m => a -> m a
return()}consequent :: PropertySeries m
consequent =forall (t :: * -> *). Env t -> Property t -> PropertySeries t
unProp Env m
env forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. Testable m a => a -> Property m
freshContext a
prop badTestHook :: Series m ()
badTestHook =forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
liftforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). Env m -> TestQuality -> m ()
testHook Env m
env TestQuality
BadTest success :: Series m PropertySuccess
success =forall (m :: * -> *) a b.
MonadLogic m =>
m a -> (a -> m b) -> m b -> m b
ifteSeries m PropertyFailure
counterExample -- then(\PropertyFailure
ex ->doSeries m ()
badTestHook forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$PropertyFailure -> PropertySuccess
Vacuously PropertyFailure
ex )-- else(forall (m :: * -> *). PropertySeries m -> Series m PropertySuccess
searchExamples PropertySeries m
consequent )failure :: Series m PropertyFailure
failure =forall (m :: * -> *) a b.
MonadLogic m =>
m a -> (a -> m b) -> m b -> m b
ifteSeries m PropertyFailure
counterExample -- then(forall a b. a -> b -> a
constforall a b. (a -> b) -> a -> b
$doforall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
liftforall a b. (a -> b) -> a -> b
$forall (m :: * -> *). Env m -> TestQuality -> m ()
testHook Env m
env TestQuality
BadTest forall (m :: * -> *) a. MonadPlus m => m a
mzero)-- else(forall (m :: * -> *). PropertySeries m -> Series m PropertyFailure
searchCounterExamples PropertySeries m
consequent )forall (m :: * -> *) a. Monad m => a -> m a
returnforall a b. (a -> b) -> a -> b
$forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure -> PropertySeries m
atomicProperty Series m PropertySuccess
success Series m PropertyFailure
failure -- | Run property with a modified depth. Affects all quantified variables-- in the property.---- @since 1.0changeDepth ::Testable m a =>(Depth ->Depth )->a ->Property m changeDepth :: forall (m :: * -> *) a.
Testable m a =>
(Int -> Int) -> a -> Property m
changeDepth Int -> Int
modifyDepth a
a =forall (m :: * -> *).
Reader (Env m) (PropertySeries m) -> Property m
Property (PropertySeries m -> PropertySeries m
changeDepthPS forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>forall (m :: * -> *).
Property m -> Reader (Env m) (PropertySeries m)
unProperty (forall (m :: * -> *) a. Testable m a => a -> Property m
test a
a ))wherechangeDepthPS :: PropertySeries m -> PropertySeries m
changeDepthPS (PropertySeries Series m PropertySuccess
ss Series m PropertyFailure
sf Series m (Property m, [Argument])
sc )=forall (m :: * -> *).
Series m PropertySuccess
-> Series m PropertyFailure
-> Series m (Property m, [Argument])
-> PropertySeries m
PropertySeries (forall (m :: * -> *) a. (Int -> Int) -> Series m a -> Series m a
localDepth Int -> Int
modifyDepth Series m PropertySuccess
ss )(forall (m :: * -> *) a. (Int -> Int) -> Series m a -> Series m a
localDepth Int -> Int
modifyDepth Series m PropertyFailure
sf )(forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first(forall (m :: * -> *) a.
Testable m a =>
(Int -> Int) -> a -> Property m
changeDepth Int -> Int
modifyDepth )forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>forall (m :: * -> *) a. (Int -> Int) -> Series m a -> Series m a
localDepth Int -> Int
modifyDepth Series m (Property m, [Argument])
sc )-- | Quantify the function's argument over its 'series', but adjust the-- depth. This doesn't affect any subsequent variables.---- @since 1.0changeDepth1 ::(Showa ,Serial m a ,Testable m b )=>(Depth ->Depth )->(a ->b )->Property m changeDepth1 :: forall a (m :: * -> *) b.
(Show a, Serial m a, Testable m b) =>
(Int -> Int) -> (a -> b) -> Property m
changeDepth1 Int -> Int
modifyDepth =forall a (m :: * -> *) b.
(Show a, Testable m b) =>
Series m a -> (a -> b) -> Property m
over forall a b. (a -> b) -> a -> b
$forall (m :: * -> *) a. (Int -> Int) -> Series m a -> Series m a
localDepth Int -> Int
modifyDepth forall (m :: * -> *) a. Serial m a => Series m a
series -- }}}

AltStyle によって変換されたページ (->オリジナル) /