-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Release with confidence. -- -- Hedgehog automatically generates a comprehensive array of test -- cases, exercising your software in ways human testers would never -- imagine. -- -- Generate hundreds of test cases automatically, exposing even the most -- insidious of corner cases. Failures are automatically simplified, -- giving developers coherent, intelligible error messages. -- -- To get started quickly, see the examples. @package hedgehog @version 1.7 -- | For compatibility across different versions of the barbie -- package. module Hedgehog.Internal.Barbie -- | Barbie-types that can be mapped over. Instances of FunctorB -- should satisfy the following laws: -- --
-- bmap id = id -- bmap f . bmap g = bmap (f . g) ---- -- There is a default bmap implementation for Generic -- types, so instances can derived automatically. class FunctorB (b :: k -> Type -> Type) bmap :: FunctorB b => (forall (a :: k). () => f a -> g a) -> b f -> b g ($dmbmap) :: forall f g. (FunctorB b, CanDeriveFunctorB b f g) => (forall (a :: k). () => f a -> g a) -> b f -> b g -- | Barbie-types that can be traversed from left to right. Instances -- should satisfy the following laws: -- --
-- t . btraverse f = btraverse (t . f) -- naturality -- btraverse Identity = Identity -- identity -- btraverse (Compose . fmap g . f) = Compose . fmap (btraverse g) . btraverse f -- composition ---- -- There is a default btraverse implementation for Generic -- types, so instances can derived automatically. class FunctorB b => TraversableB (b :: k -> Type -> Type) btraverse :: (TraversableB b, Applicative e) => (forall (a :: k). () => f a -> e (g a)) -> b f -> e (b g) ($dmbtraverse) :: forall e f g. (TraversableB b, Applicative e, CanDeriveTraversableB b f g) => (forall (a :: k). () => f a -> e (g a)) -> b f -> e (b g) newtype Rec p a (x :: k) Rec :: K1 R a x -> Rec p a (x :: k) [unRec] :: Rec p a (x :: k) -> K1 R a x module Hedgehog.Internal.Distributive class MonadTransDistributive (g :: Type -> Type -> Type -> Type) where { type Transformer (f :: Type -> Type -> Type -> Type) (g :: Type -> Type -> Type -> Type) (m :: Type -> Type); type Transformer f :: Type -> Type -> Type -> Type g :: Type -> Type -> Type -> Type m :: Type -> Type = (Monad m, Monad f m, Monad g m, Monad f g m, MonadTrans f, MFunctor f); } -- | Distribute one monad transformer over another. distributeT :: forall f (m :: Type -> Type) a. (MonadTransDistributive g, Transformer f g m) => g (f m) a -> f (g m) a instance Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.Except.ExceptT x) instance Hedgehog.Internal.Distributive.MonadTransDistributive Control.Monad.Trans.Identity.IdentityT instance Hedgehog.Internal.Distributive.MonadTransDistributive Control.Monad.Trans.Maybe.MaybeT instance GHC.Base.Monoid w => Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.RWS.Strict.RWST r w s) instance GHC.Base.Monoid w => Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.RWS.Lazy.RWST r w s) instance Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.Reader.ReaderT r) instance Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.State.Strict.StateT s) instance Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.State.Lazy.StateT s) instance GHC.Base.Monoid w => Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.Writer.Strict.WriterT w) instance GHC.Base.Monoid w => Hedgehog.Internal.Distributive.MonadTransDistributive (Control.Monad.Trans.Writer.Lazy.WriterT w) module Hedgehog.Internal.Exception tryAll :: MonadCatch m => m a -> m (Either SomeException a) tryEvaluate :: a -> Either SomeException a module Hedgehog.Internal.HTraversable -- | Higher-order traversable functors. -- -- Deprecated in favor of TraversableB which can be derived -- using GHC.Generics -- | Deprecated: Replace with Hedgehog.TraversableB (defined in -- Data.Functor.Barbie) which can be derived automatically using -- GHC.Generics class HTraversable (t :: Type -> Type -> Type) htraverse :: (HTraversable t, Applicative f) => (forall a. () => g a -> f (h a)) -> t g -> f (t h) module Hedgehog.Internal.Opaque -- | Opaque values. -- -- Useful if you want to put something without a Show instance -- inside something which you'd like to be able to display. -- -- For example: -- --
-- data State v =
-- State {
-- stateRefs :: [Var (Opaque (IORef Int)) v]
-- } deriving (Eq, Show)
--
newtype Opaque a
Opaque :: a -> Opaque a
[unOpaque] :: Opaque a -> a
instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Opaque.Opaque a)
instance GHC.Classes.Ord a => GHC.Classes.Ord (Hedgehog.Internal.Opaque.Opaque a)
instance GHC.Show.Show (Hedgehog.Internal.Opaque.Opaque a)
-- | Mostly for compatibility across different base Prelude changes.
module Hedgehog.Internal.Prelude
-- | The class of semigroups (types with an associative binary operation).
--
-- Instances should satisfy the following:
--
--
--
-- You can alternatively define sconcat instead of
-- (<>), in which case the laws are:
--
-- -- >>> [1,2,3] <> [4,5,6] -- [1,2,3,4,5,6] ---- --
-- >>> Just [1, 2, 3] <> Just [4, 5, 6] -- Just [1,2,3,4,5,6] ---- --
-- >>> putStr "Hello, " <> putStrLn "World!" -- Hello, World! --(<>) :: Semigroup a => a -> a -> a -- | Reduce a non-empty list with <> -- -- The default definition should be sufficient, but this can be -- overridden for efficiency. -- --
-- >>> import Data.List.NonEmpty (NonEmpty (..)) ---- --
-- >>> sconcat $ "Hello" :| [" ", "Haskell", "!"] -- "Hello Haskell!" ---- --
-- >>> sconcat $ Just [1, 2, 3] :| [Nothing, Just [4, 5, 6]] -- Just [1,2,3,4,5,6] ---- --
-- >>> sconcat $ Left 1 :| [Right 2, Left 3, Right 4] -- Right 2 --sconcat :: Semigroup a => NonEmpty a -> a -- | Repeat a value n times. -- -- The default definition will raise an exception for a multiplier that -- is <= 0. This may be overridden with an implementation -- that is total. For monoids it is preferred to use -- stimesMonoid. -- -- By making this a member of the class, idempotent semigroups and -- monoids can upgrade this to execute in <math> by picking -- stimes = stimesIdempotent or stimes = -- stimesIdempotentMonoid respectively. -- --
-- >>> stimes 4 [1] -- [1,1,1,1] ---- --
-- >>> stimes 5 (putStr "hi!") -- hi!hi!hi!hi!hi! ---- --
-- >>> stimes 3 (Right ":)") -- Right ":)" --stimes :: (Semigroup a, Integral b) => b -> a -> a infixr 6 <> -- | When a value is bound in do-notation, the pattern on the left -- hand side of <- might not match. In this case, this class -- provides a function to recover. -- -- A Monad without a MonadFail instance may only be used in -- conjunction with pattern that always match, such as newtypes, tuples, -- data types with only a single data constructor, and irrefutable -- patterns (~pat). -- -- Instances of MonadFail should satisfy the following law: -- fail s should be a left zero for >>=, -- --
-- fail s >>= f = fail s ---- -- If your Monad is also MonadPlus, a popular definition is -- --
-- fail _ = mzero ---- -- fail s should be an action that runs in the monad itself, not -- an exception (except in instances of MonadIO). In particular, -- fail should not be implemented in terms of error. class Monad m => MonadFail (m :: Type -> Type) -- | String is an alias for a list of characters. -- -- String constants in Haskell are values of type String. That -- means if you write a string literal like "hello world", it -- will have the type [Char], which is the same as -- String. -- -- Note: You can ask the compiler to automatically infer different -- types with the -XOverloadedStrings language extension, for -- example "hello world" :: Text. See IsString for more -- information. -- -- Because String is just a list of characters, you can use -- normal list functions to do basic string manipulation. See -- Data.List for operations on lists. -- --
-- ╭─────┬───┬──╮ ╭─────┬───┬──╮ ╭─────┬───┬──╮ ╭────╮ -- │ (:) │ │ ─┼─>│ (:) │ │ ─┼─>│ (:) │ │ ─┼─>│ [] │ -- ╰─────┴─┼─┴──╯ ╰─────┴─┼─┴──╯ ╰─────┴─┼─┴──╯ ╰────╯ -- v v v -- 'a' 'b' 'c' ---- -- The String "abc" will use 5*3+1 = 16 (in general -- 5n+1) words of space in memory. -- -- Furthermore, operations like (++) (string concatenation) are -- O(n) (in the left argument). -- -- For historical reasons, the base library uses String -- in a lot of places for the conceptual simplicity, but library code -- dealing with user-data should use the text package for Unicode -- text, or the the bytestring package for binary data. type String = [Char] -- | The Maybe type encapsulates an optional value. A value of type -- Maybe a either contains a value of type a -- (represented as Just a), or it is empty (represented -- as Nothing). Using Maybe is a good way to deal with -- errors or exceptional cases without resorting to drastic measures such -- as error. -- -- The Maybe type is also a monad. It is a simple kind of error -- monad, where all errors are represented by Nothing. A richer -- error monad can be built using the Either type. data Maybe a Nothing :: Maybe a Just :: a -> Maybe a data Bool False :: Bool True :: Bool -- | The character type Char represents Unicode codespace and its -- elements are code points as in definitions D9 and D10 of the -- Unicode Standard. -- -- Character literals in Haskell are single-quoted: 'Q', -- 'Я' or 'Ω'. To represent a single quote itself use -- '\'', and to represent a backslash use '\\'. The -- full grammar can be found in the section 2.6 of the Haskell 2010 -- Language Report. -- -- To specify a character by its code point one can use decimal, -- hexadecimal or octal notation: '\65', '\x41' and -- '\o101' are all alternative forms of 'A'. The -- largest code point is '\x10ffff'. -- -- There is a special escape syntax for ASCII control characters: -- -- TODO: table -- -- Data.Char provides utilities to work with Char. data Char -- | Double-precision floating point numbers. It is desirable that this -- type be at least equal in range and precision to the IEEE -- double-precision type. data Double -- | Single-precision floating point numbers. It is desirable that this -- type be at least equal in range and precision to the IEEE -- single-precision type. data Float -- | A fixed-precision integer type with at least the range [-2^29 .. -- 2^29-1]. The exact range for a given implementation can be -- determined by using minBound and maxBound from the -- Bounded class. data Int -- | A Word is an unsigned integral type, with the same size as -- Int. data Word data Ordering LT :: Ordering EQ :: Ordering GT :: Ordering -- | Lifted, homogeneous equality. By lifted, we mean that it can be bogus -- (deferred type error). By homogeneous, the two types a and -- b must have the same kinds. class a ~# b => (a :: k) ~ (b :: k) infix 4 ~ -- | Arbitrary precision integers. In contrast with fixed-size integral -- types such as Int, the Integer type represents the -- entire infinite range of integers. -- -- Integers are stored in a kind of sign-magnitude form, hence do not -- expect two's complement form when using bit operations. -- -- If the value is small (fit into an Int), IS constructor -- is used. Otherwise IP and IN constructors are used to -- store a BigNat representing respectively the positive or the -- negative value magnitude. -- -- Invariant: IP and IN are used iff value doesn't fit in -- IS data Integer -- | ($) is the function application operator. -- -- Applying ($) to a function f and an argument -- x gives the same result as applying f to x -- directly. The definition is akin to this: -- --
-- ($) :: (a -> b) -> a -> b -- ($) f x = f x ---- -- This is id specialized from a -> a to -- (a -> b) -> (a -> b) which by the associativity of -- (->) is the same as (a -> b) -> a -> b. -- -- On the face of it, this may appear pointless! But it's actually one of -- the most useful and important operators in Haskell. -- -- The order of operations is very different between ($) and -- normal function application. Normal function application has -- precedence 10 - higher than any operator - and associates to the left. -- So these two definitions are equivalent: -- --
-- expr = min 5 1 + 5 -- expr = ((min 5) 1) + 5 ---- -- ($) has precedence 0 (the lowest) and associates to the -- right, so these are equivalent: -- --
-- expr = min 5 $ 1 + 5 -- expr = (min 5) (1 + 5) ---- --
-- -- | Sum numbers in a string: strSum "100 5 -7" == 98 -- strSum :: String -> Int -- strSum s = sum (mapMaybe readMaybe (words s)) ---- -- we can deploy the function application operator: -- --
-- -- | Sum numbers in a string: strSum "100 5 -7" == 98 -- strSum :: String -> Int -- strSum s = sum $ mapMaybe readMaybe $ words s ---- -- ($) is also used as a section (a partially applied operator), -- in order to indicate that we wish to apply some yet-unspecified -- function to a given value. For example, to apply the argument -- 5 to a list of functions: -- --
-- applyFive :: [Int] -- applyFive = map ($ 5) [(+1), (2^)] -- >>> [6, 32] ---- --
-- fastMod :: Int -> Int -> Int -- fastMod (I# x) (I# m) = I# $ remInt# x m --($) :: (a -> b) -> a -> b infixr 0 $ -- | otherwise is defined as the value True. It helps to make -- guards more readable. eg. -- --
-- f x | x < 0 = ... -- | otherwise = ... --otherwise :: Bool -- | (++) appends two lists, i.e., -- --
-- [x1, ..., xm] ++ [y1, ..., yn] == [x1, ..., xm, y1, ..., yn] -- [x1, ..., xm] ++ [y1, ...] == [x1, ..., xm, y1, ...] ---- -- If the first list is not finite, the result is the first list. -- --
-- >>> [1, 2, 3] ++ [4, 5, 6] -- [1,2,3,4,5,6] ---- --
-- >>> [] ++ [1, 2, 3] -- [1,2,3] ---- --
-- >>> [3, 2, 1] ++ [] -- [3,2,1] --(++) :: [a] -> [a] -> [a] infixr 5 ++ -- | The Foldable class represents data structures that can be reduced to a -- summary value one element at a time. Strict left-associative folds are -- a good fit for space-efficient reduction, while lazy right-associative -- folds are a good fit for corecursive iteration, or for folds that -- short-circuit after processing an initial subsequence of the -- structure's elements. -- -- Instances can be derived automatically by enabling the -- DeriveFoldable extension. For example, a derived instance for -- a binary tree might be: -- --
-- {-# LANGUAGE DeriveFoldable #-}
-- data Tree a = Empty
-- | Leaf a
-- | Node (Tree a) a (Tree a)
-- deriving Foldable
--
--
-- A more detailed description can be found in the Overview
-- section of Data.Foldable#overview.
--
-- For the class laws see the Laws section of
-- Data.Foldable#laws.
class Foldable (t :: Type -> Type)
-- | Map each element of the structure into a monoid, and combine the
-- results with (<>). This fold is
-- right-associative and lazy in the accumulator. For strict
-- left-associative folds consider foldMap' instead.
--
--
-- >>> foldMap Sum [1, 3, 5]
-- Sum {getSum = 9}
--
--
--
-- >>> foldMap Product [1, 3, 5]
-- Product {getProduct = 15}
--
--
-- -- >>> foldMap (replicate 3) [1, 2, 3] -- [1,1,1,2,2,2,3,3,3] ---- -- When a Monoid's (<>) is lazy in its second -- argument, foldMap can return a result even from an unbounded -- structure. For example, lazy accumulation enables -- Data.ByteString.Builder to efficiently serialise large data -- structures and produce the output incrementally: -- --
-- >>> import qualified Data.ByteString.Lazy as L -- -- >>> import qualified Data.ByteString.Builder as B -- -- >>> let bld :: Int -> B.Builder; bld i = B.intDec i <> B.word8 0x20 -- -- >>> let lbs = B.toLazyByteString $ foldMap bld [0..] -- -- >>> L.take 64 lbs -- "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24" --foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m -- | Right-associative fold of a structure, lazy in the accumulator. -- -- In the case of lists, foldr, when applied to a binary operator, -- a starting value (typically the right-identity of the operator), and a -- list, reduces the list using the binary operator, from right to left: -- --
-- foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...) ---- -- Note that since the head of the resulting expression is produced by an -- application of the operator to the first element of the list, given an -- operator lazy in its right argument, foldr can produce a -- terminating expression from an unbounded list. -- -- For a general Foldable structure this should be semantically -- identical to, -- --
-- foldr f z = foldr f z . toList ---- --
-- >>> foldr (||) False [False, True, False] -- True ---- --
-- >>> foldr (||) False [] -- False ---- --
-- >>> foldr (\c acc -> acc ++ [c]) "foo" ['a', 'b', 'c', 'd'] -- "foodcba" ---- --
-- >>> foldr (||) False (True : repeat False) -- True ---- -- But the following doesn't terminate: -- --
-- >>> foldr (||) False (repeat False ++ [True]) -- * Hangs forever * ---- --
-- >>> take 5 $ foldr (\i acc -> i : fmap (+3) acc) [] (repeat 1) -- [1,4,7,10,13] --foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b -- | Left-associative fold of a structure, lazy in the accumulator. This is -- rarely what you want, but can work well for structures with efficient -- right-to-left sequencing and an operator that is lazy in its left -- argument. -- -- In the case of lists, foldl, when applied to a binary operator, -- a starting value (typically the left-identity of the operator), and a -- list, reduces the list using the binary operator, from left to right: -- --
-- foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn ---- -- Note that to produce the outermost application of the operator the -- entire input list must be traversed. Like all left-associative folds, -- foldl will diverge if given an infinite list. -- -- If you want an efficient strict left-fold, you probably want to use -- foldl' instead of foldl. The reason for this is that the -- latter does not force the inner results (e.g. z `f` x1 -- in the above example) before applying them to the operator (e.g. to -- (`f` x2)). This results in a thunk chain O(n) elements -- long, which then must be evaluated from the outside-in. -- -- For a general Foldable structure this should be semantically -- identical to: -- --
-- foldl f z = foldl f z . toList ---- --
-- >>> foldl (+) 42 [1,2,3,4] -- 52 ---- -- Though the result below is lazy, the input is reversed before -- prepending it to the initial accumulator, so corecursion begins only -- after traversing the entire input string. -- --
-- >>> foldl (\acc c -> c : acc) "abcd" "efgh" -- "hgfeabcd" ---- -- A left fold of a structure that is infinite on the right cannot -- terminate, even when for any finite input the fold just returns the -- initial accumulator: -- --
-- >>> foldl (\a _ -> a) 0 $ repeat 1 -- * Hangs forever * ---- -- WARNING: When it comes to lists, you always want to use either -- foldl' or foldr instead. foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b -- | A variant of foldr that has no base case, and thus may only be -- applied to non-empty structures. -- -- This function is non-total and will raise a runtime exception if the -- structure happens to be empty. -- --
-- >>> foldr1 (+) [1..4] -- 10 ---- --
-- >>> foldr1 (+) [] -- Exception: Prelude.foldr1: empty list ---- --
-- >>> foldr1 (+) Nothing -- *** Exception: foldr1: empty structure ---- --
-- >>> foldr1 (-) [1..4] -- -2 ---- --
-- >>> foldr1 (&&) [True, False, True, True] -- False ---- --
-- >>> foldr1 (||) [False, False, True, True] -- True ---- --
-- >>> foldr1 (+) [1..] -- * Hangs forever * --foldr1 :: Foldable t => (a -> a -> a) -> t a -> a -- | A variant of foldl that has no base case, and thus may only be -- applied to non-empty structures. -- -- This function is non-total and will raise a runtime exception if the -- structure happens to be empty. -- --
-- foldl1 f = foldl1 f . toList ---- --
-- >>> foldl1 (+) [1..4] -- 10 ---- --
-- >>> foldl1 (+) [] -- *** Exception: Prelude.foldl1: empty list ---- --
-- >>> foldl1 (+) Nothing -- *** Exception: foldl1: empty structure ---- --
-- >>> foldl1 (-) [1..4] -- -8 ---- --
-- >>> foldl1 (&&) [True, False, True, True] -- False ---- --
-- >>> foldl1 (||) [False, False, True, True] -- True ---- --
-- >>> foldl1 (+) [1..] -- * Hangs forever * --foldl1 :: Foldable t => (a -> a -> a) -> t a -> a -- | Test whether the structure is empty. The default implementation is -- Left-associative and lazy in both the initial element and the -- accumulator. Thus optimised for structures where the first element can -- be accessed in constant time. Structures where this is not the case -- should have a non-default implementation. -- --
-- >>> null [] -- True ---- --
-- >>> null [1] -- False ---- -- null is expected to terminate even for infinite structures. The -- default implementation terminates provided the structure is bounded on -- the left (there is a leftmost element). -- --
-- >>> null [1..] -- False --null :: Foldable t => t a -> Bool -- | Returns the size/length of a finite structure as an Int. The -- default implementation just counts elements starting with the -- leftmost. Instances for structures that can compute the element count -- faster than via element-by-element counting, should provide a -- specialised implementation. -- --
-- >>> length [] -- 0 ---- --
-- >>> length ['a', 'b', 'c'] -- 3 -- -- >>> length [1..] -- * Hangs forever * --length :: Foldable t => t a -> Int -- | Does the element occur in the structure? -- -- Note: elem is often used in infix form. -- --
-- >>> 3 `elem` [] -- False ---- --
-- >>> 3 `elem` [1,2] -- False ---- --
-- >>> 3 `elem` [1,2,3,4,5] -- True ---- -- For infinite structures, the default implementation of elem -- terminates if the sought-after value exists at a finite distance from -- the left side of the structure: -- --
-- >>> 3 `elem` [1..] -- True ---- --
-- >>> 3 `elem` ([4..] ++ [3]) -- * Hangs forever * --elem :: (Foldable t, Eq a) => a -> t a -> Bool -- | The largest element of a non-empty structure. -- -- This function is non-total and will raise a runtime exception if the -- structure happens to be empty. A structure that supports random access -- and maintains its elements in order should provide a specialised -- implementation to return the maximum in faster than linear time. -- --
-- >>> maximum [1..10] -- 10 ---- --
-- >>> maximum [] -- *** Exception: Prelude.maximum: empty list ---- --
-- >>> maximum Nothing -- *** Exception: maximum: empty structure ---- -- WARNING: This function is partial for possibly-empty structures like -- lists. maximum :: (Foldable t, Ord a) => t a -> a -- | The least element of a non-empty structure. -- -- This function is non-total and will raise a runtime exception if the -- structure happens to be empty. A structure that supports random access -- and maintains its elements in order should provide a specialised -- implementation to return the minimum in faster than linear time. -- --
-- >>> minimum [1..10] -- 1 ---- --
-- >>> minimum [] -- *** Exception: Prelude.minimum: empty list ---- --
-- >>> minimum Nothing -- *** Exception: minimum: empty structure ---- -- WARNING: This function is partial for possibly-empty structures like -- lists. minimum :: (Foldable t, Ord a) => t a -> a -- | The sum function computes the sum of the numbers of a -- structure. -- --
-- >>> sum [] -- 0 ---- --
-- >>> sum [42] -- 42 ---- --
-- >>> sum [1..10] -- 55 ---- --
-- >>> sum [4.1, 2.0, 1.7] -- 7.8 ---- --
-- >>> sum [1..] -- * Hangs forever * --sum :: (Foldable t, Num a) => t a -> a -- | The product function computes the product of the numbers of a -- structure. -- --
-- >>> product [] -- 1 ---- --
-- >>> product [42] -- 42 ---- --
-- >>> product [1..10] -- 3628800 ---- --
-- >>> product [4.1, 2.0, 1.7] -- 13.939999999999998 ---- --
-- >>> product [1..] -- * Hangs forever * --product :: (Foldable t, Num a) => t a -> a infix 4 `elem` -- | The Monad class defines the basic operations over a -- monad, a concept from a branch of mathematics known as -- category theory. From the perspective of a Haskell programmer, -- however, it is best to think of a monad as an abstract datatype -- of actions. Haskell's do expressions provide a convenient -- syntax for writing monadic expressions. -- -- Instances of Monad should satisfy the following: -- --
-- do a <- as -- bs a --(>>=) :: Monad m => m a -> (a -> m b) -> m b -- | Sequentially compose two actions, discarding any value produced by the -- first, like sequencing operators (such as the semicolon) in imperative -- languages. -- -- 'as >> bs' can be understood as the do -- expression -- --
-- do as -- bs --(>>) :: Monad m => m a -> m b -> m b -- | Inject a value into the monadic type. return :: Monad m => a -> m a infixl 1 >>= infixl 1 >> -- | A type f is a Functor if it provides a function fmap -- which, given any types a and b lets you apply any -- function from (a -> b) to turn an f a into an -- f b, preserving the structure of f. Furthermore -- f needs to adhere to the following: -- -- -- -- Note, that the second law follows from the free theorem of the type -- fmap and the first law, so you need only check that the former -- condition holds. See -- https://www.schoolofhaskell.com/user/edwardk/snippets/fmap or -- https://github.com/quchen/articles/blob/master/second_functor_law.md -- for an explanation. class Functor (f :: Type -> Type) -- | fmap is used to apply a function of type (a -> b) -- to a value of type f a, where f is a functor, to produce a -- value of type f b. Note that for any type constructor with -- more than one parameter (e.g., Either), only the last type -- parameter can be modified with fmap (e.g., b in -- `Either a b`). -- -- Some type constructors with two parameters or more have a -- Bifunctor instance that allows both the last and the -- penultimate parameters to be mapped over. -- --
-- >>> fmap show Nothing -- Nothing -- -- >>> fmap show (Just 3) -- Just "3" ---- -- Convert from an Either Int Int to an Either Int -- String using show: -- --
-- >>> fmap show (Left 17) -- Left 17 -- -- >>> fmap show (Right 17) -- Right "17" ---- -- Double each element of a list: -- --
-- >>> fmap (*2) [1,2,3] -- [2,4,6] ---- -- Apply even to the second element of a pair: -- --
-- >>> fmap even (2,2) -- (2,True) ---- -- It may seem surprising that the function is only applied to the last -- element of the tuple compared to the list example above which applies -- it to every element in the list. To understand, remember that tuples -- are type constructors with multiple type parameters: a tuple of 3 -- elements (a,b,c) can also be written (,,) a b c and -- its Functor instance is defined for Functor ((,,) a -- b) (i.e., only the third parameter is free to be mapped over with -- fmap). -- -- It explains why fmap can be used with tuples containing -- values of different types as in the following example: -- --
-- >>> fmap even ("hello", 1.0, 4)
-- ("hello",1.0,True)
--
fmap :: Functor f => (a -> b) -> f a -> f b
-- | Replace all locations in the input with the same value. The default
-- definition is fmap . const, but this may be
-- overridden with a more efficient version.
--
-- -- >>> 'a' <$ Just 2 -- Just 'a' -- -- >>> 'a' <$ Nothing -- Nothing --(<$) :: Functor f => a -> f b -> f a infixl 4 <$ -- | A functor with application, providing operations to -- --
-- (<*>) = liftA2 id ---- --
-- liftA2 f x y = f <$> x <*> y ---- -- Further, any definition must satisfy the following: -- --
pure id <*> v = -- v
pure (.) <*> u -- <*> v <*> w = u <*> (v -- <*> w)
pure f <*> -- pure x = pure (f x)
u <*> pure y = -- pure ($ y) <*> u
-- forall x y. p (q x y) = f x . g y ---- -- it follows from the above that -- --
-- liftA2 p (liftA2 q u v) = liftA2 f u . liftA2 g v ---- -- If f is also a Monad, it should satisfy -- -- -- -- (which implies that pure and <*> satisfy the -- applicative functor laws). class Functor f => Applicative (f :: Type -> Type) -- | Lift a value. pure :: Applicative f => a -> f a -- | Sequential application. -- -- A few functors support an implementation of <*> that is -- more efficient than the default one. -- --
-- >>> data MyState = MyState {arg1 :: Foo, arg2 :: Bar, arg3 :: Baz}
--
--
-- -- >>> produceFoo :: Applicative f => f Foo ---- --
-- >>> produceBar :: Applicative f => f Bar -- -- >>> produceBaz :: Applicative f => f Baz ---- --
-- >>> mkState :: Applicative f => f MyState -- -- >>> mkState = MyState <$> produceFoo <*> produceBar <*> produceBaz --(<*>) :: Applicative f => f (a -> b) -> f a -> f b -- | Lift a binary function to actions. -- -- Some functors support an implementation of liftA2 that is more -- efficient than the default one. In particular, if fmap is an -- expensive operation, it is likely better to use liftA2 than to -- fmap over the structure and then use <*>. -- -- This became a typeclass method in 4.10.0.0. Prior to that, it was a -- function defined in terms of <*> and fmap. -- --
-- >>> liftA2 (,) (Just 3) (Just 5) -- Just (3,5) --liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c -- | Sequence actions, discarding the value of the first argument. -- --
-- >>> Just 2 *> Just 3 -- Just 3 ---- --
-- >>> Nothing *> Just 3 -- Nothing ---- -- Of course a more interesting use case would be to have effectful -- computations instead of just returning pure values. -- --
-- >>> import Data.Char
--
-- >>> import Text.ParserCombinators.ReadP
--
-- >>> let p = string "my name is " *> munch1 isAlpha <* eof
--
-- >>> readP_to_S p "my name is Simon"
-- [("Simon","")]
--
(*>) :: Applicative f => f a -> f b -> f b
-- | Sequence actions, discarding the value of the second argument.
(<*) :: Applicative f => f a -> f b -> f a
infixl 4 <*>
infixl 4 *>
infixl 4 <*
-- | The class of monoids (types with an associative binary operation that
-- has an identity). Instances should satisfy the following:
--
-- -- >>> "Hello world" <> mempty -- "Hello world" ---- --
-- >>> mempty <> [1, 2, 3] -- [1,2,3] --mempty :: Monoid a => a -- | An associative operation -- -- NOTE: This method is redundant and has the default -- implementation mappend = (<>) since -- base-4.11.0.0. Should it be implemented manually, since -- mappend is a synonym for (<>), it is expected that -- the two functions are defined the same way. In a future GHC release -- mappend will be removed from Monoid. mappend :: Monoid a => a -> a -> a -- | Fold a list using the monoid. -- -- For most types, the default definition for mconcat will be -- used, but the function is included in the class definition so that an -- optimized version can be provided for specific types. -- --
-- >>> mconcat ["Hello", " ", "Haskell", "!"] -- "Hello Haskell!" --mconcat :: Monoid a => [a] -> a -- | The class of semigroups (types with an associative binary operation). -- -- Instances should satisfy the following: -- -- -- -- You can alternatively define sconcat instead of -- (<>), in which case the laws are: -- --
-- >>> [1,2,3] <> [4,5,6] -- [1,2,3,4,5,6] ---- --
-- >>> Just [1, 2, 3] <> Just [4, 5, 6] -- Just [1,2,3,4,5,6] ---- --
-- >>> putStr "Hello, " <> putStrLn "World!" -- Hello, World! --(<>) :: Semigroup a => a -> a -> a infixr 6 <> -- | A value of type IO a is a computation which, when -- performed, does some I/O before returning a value of type a. -- -- There is really only one way to "perform" an I/O action: bind it to -- Main.main in your program. When your program is run, the I/O -- will be performed. It isn't possible to perform I/O from an arbitrary -- function, unless that function is itself in the IO monad and -- called at some point, directly or indirectly, from Main.main. -- -- IO is a monad, so IO actions can be combined using -- either the do-notation or the >> and >>= -- operations from the Monad class. data IO a -- | Functors representing data structures that can be transformed to -- structures of the same shape by performing an -- Applicative (or, therefore, Monad) action on each -- element from left to right. -- -- A more detailed description of what same shape means, the -- various methods, how traversals are constructed, and example advanced -- use-cases can be found in the Overview section of -- Data.Traversable#overview. -- -- For the class laws see the Laws section of -- Data.Traversable#laws. class (Functor t, Foldable t) => Traversable (t :: Type -> Type) -- | Map each element of a structure to an action, evaluate these actions -- from left to right, and collect the results. For a version that -- ignores the results see traverse_. -- --
-- >>> traverse Just [1,2,3,4] -- Just [1,2,3,4] ---- --
-- >>> traverse id [Right 1, Right 2, Right 3, Right 4] -- Right [1,2,3,4] ---- -- In the next examples, we show that Nothing and Left -- values short circuit the created structure. -- --
-- >>> traverse (const Nothing) [1,2,3,4] -- Nothing ---- --
-- >>> traverse (\x -> if odd x then Just x else Nothing) [1,2,3,4] -- Nothing ---- --
-- >>> traverse id [Right 1, Right 2, Right 3, Right 4, Left 0] -- Left 0 --traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) -- | Evaluate each action in the structure from left to right, and collect -- the results. For a version that ignores the results see -- sequenceA_. -- --
-- >>> sequenceA [Just 1, Just 2, Just 3] -- Just [1,2,3] ---- --
-- >>> sequenceA [Right 1, Right 2, Right 3] -- Right [1,2,3] ---- -- The next two example show Nothing and Just will short -- circuit the resulting structure if present in the input. For more -- context, check the Traversable instances for Either and -- Maybe. -- --
-- >>> sequenceA [Just 1, Just 2, Just 3, Nothing] -- Nothing ---- --
-- >>> sequenceA [Right 1, Right 2, Right 3, Left 4] -- Left 4 --sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a) -- | Map each element of a structure to a monadic action, evaluate these -- actions from left to right, and collect the results. For a version -- that ignores the results see mapM_. -- --
-- >>> sequence $ Right [1,2,3,4] -- [Right 1,Right 2,Right 3,Right 4] ---- --
-- >>> sequence $ [Right 1,Right 2,Right 3,Right 4] -- Right [1,2,3,4] ---- -- The following examples demonstrate short circuit behavior for -- sequence. -- --
-- >>> sequence $ Left [1,2,3,4] -- Left [1,2,3,4] ---- --
-- >>> sequence $ [Left 0, Right 1,Right 2,Right 3,Right 4] -- Left 0 --sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) -- | Map each element of a structure to a monadic action, evaluate these -- actions from left to right, and ignore the results. For a version that -- doesn't ignore the results see mapM. -- -- mapM_ is just like traverse_, but specialised to monadic -- actions. mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m () -- | Same as >>=, but with the arguments interchanged. (=<<) :: Monad m => (a -> m b) -> m a -> m b infixr 1 =<< -- | <math>. zipWith generalises zip by zipping with -- the function given as the first argument, instead of a tupling -- function. -- --
-- zipWith (,) xs ys == zip xs ys -- zipWith f [x1,x2,x3..] [y1,y2,y3..] == [f x1 y1, f x2 y2, f x3 y3..] ---- -- zipWith is right-lazy: -- --
-- >>> let f = undefined -- -- >>> zipWith f [] undefined -- [] ---- -- zipWith is capable of list fusion, but it is restricted to its -- first list argument and its resulting list. -- --
-- >>> zipWith (+) [1, 2, 3] [4, 5, 6] -- [5,7,9] ---- --
-- >>> zipWith (++) ["hello ", "foo"] ["world!", "bar"] -- ["hello world!","foobar"] --zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] -- | <math>. The zipWith3 function takes a function which -- combines three elements, as well as three lists and returns a list of -- the function applied to corresponding elements, analogous to -- zipWith. It is capable of list fusion, but it is restricted to -- its first list argument and its resulting list. -- --
-- zipWith3 (,,) xs ys zs == zip3 xs ys zs -- zipWith3 f [x1,x2,x3..] [y1,y2,y3..] [z1,z2,z3..] == [f x1 y1 z1, f x2 y2 z2, f x3 y3 z3..] ---- --
-- >>> zipWith3 (\x y z -> [x, y, z]) "123" "abc" "xyz" -- ["1ax","2by","3cz"] ---- --
-- >>> zipWith3 (\x y z -> (x * y) + z) [1, 2, 3] [4, 5, 6] [7, 8, 9] -- [11,18,27] --zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d] -- | Conversion of values to readable Strings. -- -- Derived instances of Show have the following properties, which -- are compatible with derived instances of Read: -- --
-- infixr 5 :^: -- data Tree a = Leaf a | Tree a :^: Tree a ---- -- the derived instance of Show is equivalent to -- --
-- instance (Show a) => Show (Tree a) where -- -- showsPrec d (Leaf m) = showParen (d > app_prec) $ -- showString "Leaf " . showsPrec (app_prec+1) m -- where app_prec = 10 -- -- showsPrec d (u :^: v) = showParen (d > up_prec) $ -- showsPrec (up_prec+1) u . -- showString " :^: " . -- showsPrec (up_prec+1) v -- where up_prec = 5 ---- -- Note that right-associativity of :^: is ignored. For example, -- --
-- showsPrec d x r ++ s == showsPrec d x (r ++ s) ---- -- Derived instances of Read and Show satisfy the -- following: -- -- -- -- That is, readsPrec parses the string produced by -- showsPrec, and delivers the value that showsPrec started -- with. showsPrec :: Show a => Int -> a -> ShowS -- | A specialised variant of showsPrec, using precedence context -- zero, and returning an ordinary String. show :: Show a => a -> String -- | The method showList is provided to allow the programmer to give -- a specialised way of showing lists of values. For example, this is -- used by the predefined Show instance of the Char type, -- where values of type String should be shown in double quotes, -- rather than between square brackets. showList :: Show a => [a] -> ShowS -- | Identity function. -- --
-- id x = x ---- -- This function might seem useless at first glance, but it can be very -- useful in a higher order context. -- --
-- >>> length $ filter id [True, True, False, True] -- 3 ---- --
-- >>> Just (Just 3) >>= id -- Just 3 ---- --
-- >>> foldr id 0 [(^3), (*5), (+2)] -- 1000 --id :: a -> a -- | unzip transforms a list of pairs into a list of first -- components and a list of second components. -- --
-- >>> unzip [] -- ([],[]) ---- --
-- >>> unzip [(1, 'a'), (2, 'b')] -- ([1,2],"ab") --unzip :: [(a, b)] -> ([a], [b]) -- | <math>. zip takes two lists and returns a list of -- corresponding pairs. -- -- zip is right-lazy: -- --
-- >>> zip [] undefined -- [] -- -- >>> zip undefined [] -- *** Exception: Prelude.undefined -- ... ---- -- zip is capable of list fusion, but it is restricted to its -- first list argument and its resulting list. -- --
-- >>> zip [1, 2, 3] ['a', 'b', 'c'] -- [(1,'a'),(2,'b'),(3,'c')] ---- -- If one input list is shorter than the other, excess elements of the -- longer list are discarded, even if one of the lists is infinite: -- --
-- >>> zip [1] ['a', 'b'] -- [(1,'a')] ---- --
-- >>> zip [1, 2] ['a'] -- [(1,'a')] ---- --
-- >>> zip [] [1..] -- [] ---- --
-- >>> zip [1..] [] -- [] --zip :: [a] -> [b] -> [(a, b)] -- | The Either type represents values with two possibilities: a -- value of type Either a b is either Left -- a or Right b. -- -- The Either type is sometimes used to represent a value which is -- either correct or an error; by convention, the Left constructor -- is used to hold an error value and the Right constructor is -- used to hold a correct value (mnemonic: "right" also means "correct"). -- --
-- >>> let s = Left "foo" :: Either String Int -- -- >>> s -- Left "foo" -- -- >>> let n = Right 3 :: Either String Int -- -- >>> n -- Right 3 -- -- >>> :type s -- s :: Either String Int -- -- >>> :type n -- n :: Either String Int ---- -- The fmap from our Functor instance will ignore -- Left values, but will apply the supplied function to values -- contained in a Right: -- --
-- >>> let s = Left "foo" :: Either String Int -- -- >>> let n = Right 3 :: Either String Int -- -- >>> fmap (*2) s -- Left "foo" -- -- >>> fmap (*2) n -- Right 6 ---- -- The Monad instance for Either allows us to chain -- together multiple actions which may fail, and fail overall if any of -- the individual steps failed. First we'll write a function that can -- either parse an Int from a Char, or fail. -- --
-- >>> import Data.Char ( digitToInt, isDigit )
--
-- >>> :{
-- let parseEither :: Char -> Either String Int
-- parseEither c
-- | isDigit c = Right (digitToInt c)
-- | otherwise = Left "parse error"
--
-- >>> :}
--
--
-- The following should work, since both '1' and '2'
-- can be parsed as Ints.
--
--
-- >>> :{
-- let parseMultiple :: Either String Int
-- parseMultiple = do
-- x <- parseEither '1'
-- y <- parseEither '2'
-- return (x + y)
--
-- >>> :}
--
--
-- -- >>> parseMultiple -- Right 3 ---- -- But the following should fail overall, since the first operation where -- we attempt to parse 'm' as an Int will fail: -- --
-- >>> :{
-- let parseMultiple :: Either String Int
-- parseMultiple = do
-- x <- parseEither 'm'
-- y <- parseEither '2'
-- return (x + y)
--
-- >>> :}
--
--
-- -- >>> parseMultiple -- Left "parse error" --data Either a b Left :: a -> Either a b Right :: b -> Either a b -- | The concatenation of all the elements of a container of lists. -- --
-- >>> concat (Just [1, 2, 3]) -- [1,2,3] ---- --
-- >>> concat (Left 42) -- [] ---- --
-- >>> concat [[1, 2, 3], [4, 5], [6], []] -- [1,2,3,4,5,6] --concat :: Foldable t => t [a] -> [a] -- | error stops execution and displays an error message. error :: HasCallStack => [Char] -> a even :: Integral a => a -> Bool -- | An infix synonym for fmap. -- -- The name of this operator is an allusion to $. Note the -- similarities between their types: -- --
-- ($) :: (a -> b) -> a -> b -- (<$>) :: Functor f => (a -> b) -> f a -> f b ---- -- Whereas $ is function application, <$> is function -- application lifted over a Functor. -- --
-- >>> show <$> Nothing -- Nothing -- -- >>> show <$> Just 3 -- Just "3" ---- -- Convert from an Either Int Int to an -- Either Int String using show: -- --
-- >>> show <$> Left 17 -- Left 17 -- -- >>> show <$> Right 17 -- Right "17" ---- -- Double each element of a list: -- --
-- >>> (*2) <$> [1,2,3] -- [2,4,6] ---- -- Apply even to the second element of a pair: -- --
-- >>> even <$> (2,2) -- (2,True) --(<$>) :: Functor f => (a -> b) -> f a -> f b infixl 4 <$> -- | Class Enum defines operations on sequentially ordered types. -- -- The enumFrom... methods are used in Haskell's translation of -- arithmetic sequences. -- -- Instances of Enum may be derived for any enumeration type -- (types whose constructors have no fields). The nullary constructors -- are assumed to be numbered left-to-right by fromEnum from -- 0 through n-1. See Chapter 10 of the Haskell -- Report for more details. -- -- For any type that is an instance of class Bounded as well as -- Enum, the following should hold: -- --
-- enumFrom x = enumFromTo x maxBound -- enumFromThen x y = enumFromThenTo x y bound -- where -- bound | fromEnum y >= fromEnum x = maxBound -- | otherwise = minBound --class Enum a -- | the successor of a value. For numeric types, succ adds 1. succ :: Enum a => a -> a -- | the predecessor of a value. For numeric types, pred subtracts -- 1. pred :: Enum a => a -> a -- | Convert from an Int. toEnum :: Enum a => Int -> a -- | Convert to an Int. It is implementation-dependent what -- fromEnum returns when applied to a value that is too large to -- fit in an Int. fromEnum :: Enum a => a -> Int -- | Used in Haskell's translation of [n..] with [n..] = -- enumFrom n, a possible implementation being enumFrom n = n : -- enumFrom (succ n). For example: -- --
enumFrom 4 :: [Integer] = [4,5,6,7,...]
enumFrom 6 :: [Int] = [6,7,8,9,...,maxBound :: -- Int]
enumFromThen 4 6 :: [Integer] = [4,6,8,10...]
enumFromThen 6 2 :: [Int] = [6,2,-2,-6,...,minBound :: -- Int]
enumFromTo 6 10 :: [Int] = [6,7,8,9,10]
enumFromTo 42 1 :: [Integer] = []
enumFromThenTo 4 2 -6 :: [Integer] = -- [4,2,0,-2,-4,-6]
enumFromThenTo 6 8 2 :: [Int] = []
-- (x `quot` y)*y + (x `rem` y) == x ---- -- WARNING: This function is partial (because it throws when 0 is passed -- as the divisor) for all the integer types in base. rem :: Integral a => a -> a -> a -- | integer division truncated toward negative infinity -- -- WARNING: This function is partial (because it throws when 0 is passed -- as the divisor) for all the integer types in base. div :: Integral a => a -> a -> a -- | integer modulus, satisfying -- --
-- (x `div` y)*y + (x `mod` y) == x ---- -- WARNING: This function is partial (because it throws when 0 is passed -- as the divisor) for all the integer types in base. mod :: Integral a => a -> a -> a -- | simultaneous quot and rem -- -- WARNING: This function is partial (because it throws when 0 is passed -- as the divisor) for all the integer types in base. quotRem :: Integral a => a -> a -> (a, a) -- | simultaneous div and mod -- -- WARNING: This function is partial (because it throws when 0 is passed -- as the divisor) for all the integer types in base. divMod :: Integral a => a -> a -> (a, a) -- | conversion to Integer toInteger :: Integral a => a -> Integer infixl 7 `quot` infixl 7 `rem` infixl 7 `div` infixl 7 `mod` -- | Arbitrary-precision rational numbers, represented as a ratio of two -- Integer values. A rational number may be constructed using the -- % operator. type Rational = Ratio Integer -- | repeat x is an infinite list, with x the -- value of every element. -- --
-- >>> take 10 $ repeat 17 -- [17,17,17,17,17,17,17,17,17, 17] ---- --
-- >>> repeat undefined -- [*** Exception: Prelude.undefined --repeat :: a -> [a] -- | cycle ties a finite list into a circular one, or equivalently, -- the infinite repetition of the original list. It is the identity on -- infinite lists. -- --
-- >>> cycle [] -- *** Exception: Prelude.cycle: empty list ---- --
-- >>> take 10 (cycle [42]) -- [42,42,42,42,42,42,42,42,42,42] ---- --
-- >>> take 10 (cycle [2, 5, 7]) -- [2,5,7,2,5,7,2,5,7,2] ---- --
-- >>> take 1 (cycle (42 : undefined)) -- [42] --cycle :: HasCallStack => [a] -> [a] -- | Parsing of Strings, producing values. -- -- Derived instances of Read make the following assumptions, which -- derived instances of Show obey: -- --
-- infixr 5 :^: -- data Tree a = Leaf a | Tree a :^: Tree a ---- -- the derived instance of Read in Haskell 2010 is equivalent to -- --
-- instance (Read a) => Read (Tree a) where
--
-- readsPrec d r = readParen (d > app_prec)
-- (\r -> [(Leaf m,t) |
-- ("Leaf",s) <- lex r,
-- (m,t) <- readsPrec (app_prec+1) s]) r
--
-- ++ readParen (d > up_prec)
-- (\r -> [(u:^:v,w) |
-- (u,s) <- readsPrec (up_prec+1) r,
-- (":^:",t) <- lex s,
-- (v,w) <- readsPrec (up_prec+1) t]) r
--
-- where app_prec = 10
-- up_prec = 5
--
--
-- Note that right-associativity of :^: is unused.
--
-- The derived instance in GHC is equivalent to
--
-- -- instance (Read a) => Read (Tree a) where -- -- readPrec = parens $ (prec app_prec $ do -- Ident "Leaf" <- lexP -- m <- step readPrec -- return (Leaf m)) -- -- +++ (prec up_prec $ do -- u <- step readPrec -- Symbol ":^:" <- lexP -- v <- step readPrec -- return (u :^: v)) -- -- where app_prec = 10 -- up_prec = 5 -- -- readListPrec = readListPrecDefault ---- -- Why do both readsPrec and readPrec exist, and why does -- GHC opt to implement readPrec in derived Read instances -- instead of readsPrec? The reason is that readsPrec is -- based on the ReadS type, and although ReadS is mentioned -- in the Haskell 2010 Report, it is not a very efficient parser data -- structure. -- -- readPrec, on the other hand, is based on a much more efficient -- ReadPrec datatype (a.k.a "new-style parsers"), but its -- definition relies on the use of the RankNTypes language -- extension. Therefore, readPrec (and its cousin, -- readListPrec) are marked as GHC-only. Nevertheless, it is -- recommended to use readPrec instead of readsPrec -- whenever possible for the efficiency improvements it brings. -- -- As mentioned above, derived Read instances in GHC will -- implement readPrec instead of readsPrec. The default -- implementations of readsPrec (and its cousin, readList) -- will simply use readPrec under the hood. If you are writing a -- Read instance by hand, it is recommended to write it like so: -- --
-- instance Read T where -- readPrec = ... -- readListPrec = readListPrecDefault --class Read a -- | attempts to parse a value from the front of the string, returning a -- list of (parsed value, remaining string) pairs. If there is no -- successful parse, the returned list is empty. -- -- Derived instances of Read and Show satisfy the -- following: -- -- -- -- That is, readsPrec parses the string produced by -- showsPrec, and delivers the value that showsPrec started -- with. readsPrec :: Read a => Int -> ReadS a -- | The method readList is provided to allow the programmer to give -- a specialised way of parsing lists of values. For example, this is -- used by the predefined Read instance of the Char type, -- where values of type String are expected to use double quotes, -- rather than square brackets. readList :: Read a => ReadS [a] -- | uncurry converts a curried function to a function on pairs. -- --
-- >>> uncurry (+) (1,2) -- 3 ---- --
-- >>> uncurry ($) (show, 1) -- "1" ---- --
-- >>> map (uncurry max) [(1,2), (3,4), (6,8)] -- [2,4,8] --uncurry :: (a -> b -> c) -> (a, b) -> c -- | <math>. Extract the first element of a list, which must be -- non-empty. -- --
-- >>> head [1, 2, 3] -- 1 ---- --
-- >>> head [1..] -- 1 ---- --
-- >>> head [] -- *** Exception: Prelude.head: empty list --head :: HasCallStack => [a] -> a -- | The Haskell 2010 type for exceptions in the IO monad. Any I/O -- operation may raise an IOError instead of returning a result. -- For a more general type of exception, including also those that arise -- in pure code, see Exception. -- -- In Haskell 2010, this is an opaque type. type IOError = IOException -- | The computation writeFile file str function writes the -- string str, to the file file. writeFile :: FilePath -> String -> IO () -- | Read a line from the standard input device (same as hGetLine -- stdin). getLine :: IO String -- | The same as putStr, but adds a newline character. putStrLn :: String -> IO () -- | Evaluate each monadic action in the structure from left to right, and -- ignore the results. For a version that doesn't ignore the results see -- sequence. -- -- sequence_ is just like sequenceA_, but specialised to -- monadic actions. sequence_ :: (Foldable t, Monad m) => t (m a) -> m () -- | const x y always evaluates to x, ignoring its second -- argument. -- --
-- const x = \_ -> x ---- -- This function might seem useless at first glance, but it can be very -- useful in a higher order context. -- --
-- >>> const 42 "hello" -- 42 ---- --
-- >>> map (const 42) [0..3] -- [42,42,42,42] --const :: a -> b -> a -- | The value of seq a b is bottom if a is -- bottom, and otherwise equal to b. In other words, it -- evaluates the first argument a to weak head normal form -- (WHNF). seq is usually introduced to improve performance by -- avoiding unneeded laziness. -- -- A note on evaluation order: the expression seq a b -- does not guarantee that a will be evaluated before -- b. The only guarantee given by seq is that the both -- a and b will be evaluated before seq returns -- a value. In particular, this means that b may be evaluated -- before a. If you need to guarantee a specific order of -- evaluation, you must use the function pseq from the -- "parallel" package. seq :: a -> b -> b infixr 0 `seq` -- | Basic numeric class. -- -- The Haskell Report defines no laws for Num. However, -- (+) and (*) are customarily expected -- to define a ring and have the following properties: -- --
-- abs x * signum x == x ---- -- For real numbers, the signum is either -1 (negative), -- 0 (zero) or 1 (positive). signum :: Num a => a -> a -- | Conversion from an Integer. An integer literal represents the -- application of the function fromInteger to the appropriate -- value of type Integer, so such literals have type -- (Num a) => a. fromInteger :: Num a => Integer -> a infixl 6 - infixl 6 + infixl 7 * -- | Fractional numbers, supporting real division. -- -- The Haskell Report defines no laws for Fractional. However, -- (+) and (*) are customarily expected -- to define a division ring and have the following properties: -- --
-- fail s >>= f = fail s ---- -- If your Monad is also MonadPlus, a popular definition is -- --
-- fail _ = mzero ---- -- fail s should be an action that runs in the monad itself, not -- an exception (except in instances of MonadIO). In particular, -- fail should not be implemented in terms of error. class Monad m => MonadFail (m :: Type -> Type) fail :: MonadFail m => String -> m a -- | General coercion from Integral types. -- -- WARNING: This function performs silent truncation if the result type -- is not at least as big as the argument's type. fromIntegral :: (Integral a, Num b) => a -> b -- | General coercion to Fractional types. -- -- WARNING: This function goes through the Rational type, which -- does not have values for NaN for example. This means it does -- not round-trip. -- -- For Double it also behaves differently with or without -O0: -- --
-- Prelude> realToFrac nan -- With -O0 -- -Infinity -- Prelude> realToFrac nan -- NaN --realToFrac :: (Real a, Fractional b) => a -> b -- | Real numbers. -- -- The Haskell report defines no laws for Real, however -- Real instances are customarily expected to adhere to the -- following law: -- --
-- (f . g) x = f (g x) ---- --
-- f . id = f = id . f ---- --
-- >>> map ((*2) . length) [[], [0, 1, 2], [0]] -- [0,6,2] ---- --
-- >>> foldr (.) id [(+1), (*3), (^3)] 2 -- 25 ---- --
-- >>> let (...) = (.).(.) in ((*2)...(+)) 5 10 -- 30 --(.) :: (b -> c) -> (a -> b) -> a -> c infixr 9 . -- | flip f takes its (first) two arguments in the reverse -- order of f. -- --
-- flip f x y = f y x ---- --
-- flip . flip = id ---- --
-- >>> flip (++) "hello" "world" -- "worldhello" ---- --
-- >>> let (.>) = flip (.) in (+1) .> show $ 5 -- "6" --flip :: (a -> b -> c) -> b -> a -> c -- | Strict (call-by-value) application operator. It takes a function and -- an argument, evaluates the argument to weak head normal form (WHNF), -- then calls the function with that value. ($!) :: (a -> b) -> a -> b infixr 0 $! -- | until p f yields the result of applying f -- until p holds. until :: (a -> Bool) -> (a -> a) -> a -> a -- | asTypeOf is a type-restricted version of const. It is -- usually used as an infix operator, and its typing forces its first -- argument (which is usually overloaded) to have the same type as the -- second. asTypeOf :: a -> a -> a -- | the same as flip (-). -- -- Because - is treated specially in the Haskell grammar, -- (- e) is not a section, but an application of -- prefix negation. However, (subtract -- exp) is equivalent to the disallowed section. subtract :: Num a => a -> a -> a -- | The maybe function takes a default value, a function, and a -- Maybe value. If the Maybe value is Nothing, the -- function returns the default value. Otherwise, it applies the function -- to the value inside the Just and returns the result. -- --
-- >>> maybe False odd (Just 3) -- True ---- --
-- >>> maybe False odd Nothing -- False ---- -- Read an integer from a string using readMaybe. If we succeed, -- return twice the integer; that is, apply (*2) to it. If -- instead we fail to parse an integer, return 0 by default: -- --
-- >>> import Text.Read ( readMaybe ) -- -- >>> maybe 0 (*2) (readMaybe "5") -- 10 -- -- >>> maybe 0 (*2) (readMaybe "") -- 0 ---- -- Apply show to a Maybe Int. If we have Just n, -- we want to show the underlying Int n. But if we have -- Nothing, we return the empty string instead of (for example) -- "Nothing": -- --
-- >>> maybe "" show (Just 5) -- "5" -- -- >>> maybe "" show Nothing -- "" --maybe :: b -> (a -> b) -> Maybe a -> b -- | <math>. Extract the elements after the head of a list, which -- must be non-empty. -- --
-- >>> tail [1, 2, 3] -- [2,3] ---- --
-- >>> tail [1] -- [] ---- --
-- >>> tail [] -- *** Exception: Prelude.tail: empty list --tail :: HasCallStack => [a] -> [a] -- | <math>. Extract the last element of a list, which must be finite -- and non-empty. -- -- WARNING: This function is partial. Consider using unsnoc -- instead. -- --
-- >>> last [1, 2, 3] -- 3 ---- --
-- >>> last [1..] -- * Hangs forever * ---- --
-- >>> last [] -- *** Exception: Prelude.last: empty list --last :: HasCallStack => [a] -> a -- | <math>. Return all the elements of a list except the last one. -- The list must be non-empty. -- -- WARNING: This function is partial. Consider using unsnoc -- instead. -- --
-- >>> init [1, 2, 3] -- [1,2] ---- --
-- >>> init [1] -- [] ---- --
-- >>> init [] -- *** Exception: Prelude.init: empty list --init :: HasCallStack => [a] -> [a] -- | <math>. scanl is similar to foldl, but returns a -- list of successive reduced values from the left: -- --
-- scanl f z [x1, x2, ...] == [z, z `f` x1, (z `f` x1) `f` x2, ...] ---- -- Note that -- --
-- last (scanl f z xs) == foldl f z xs ---- --
-- >>> scanl (+) 0 [1..4] -- [0,1,3,6,10] ---- --
-- >>> scanl (+) 42 [] -- [42] ---- --
-- >>> scanl (-) 100 [1..4] -- [100,99,97,94,90] ---- --
-- >>> scanl (\reversedString nextChar -> nextChar : reversedString) "foo" ['a', 'b', 'c', 'd'] -- ["foo","afoo","bafoo","cbafoo","dcbafoo"] ---- --
-- >>> take 10 (scanl (+) 0 [1..]) -- [0,1,3,6,10,15,21,28,36,45] ---- --
-- >>> take 1 (scanl undefined 'a' undefined) -- "a" --scanl :: (b -> a -> b) -> b -> [a] -> [b] -- | <math>. scanl1 is a variant of scanl that has no -- starting value argument: -- --
-- scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...] ---- --
-- >>> scanl1 (+) [1..4] -- [1,3,6,10] ---- --
-- >>> scanl1 (+) [] -- [] ---- --
-- >>> scanl1 (-) [1..4] -- [1,-1,-4,-8] ---- --
-- >>> scanl1 (&&) [True, False, True, True] -- [True,False,False,False] ---- --
-- >>> scanl1 (||) [False, False, True, True] -- [False,False,True,True] ---- --
-- >>> take 10 (scanl1 (+) [1..]) -- [1,3,6,10,15,21,28,36,45,55] ---- --
-- >>> take 1 (scanl1 undefined ('a' : undefined))
-- "a"
--
scanl1 :: (a -> a -> a) -> [a] -> [a]
-- | <math>. scanr is the right-to-left dual of scanl.
-- Note that the order of parameters on the accumulating function are
-- reversed compared to scanl. Also note that
--
-- -- head (scanr f z xs) == foldr f z xs. ---- --
-- >>> scanr (+) 0 [1..4] -- [10,9,7,4,0] ---- --
-- >>> scanr (+) 42 [] -- [42] ---- --
-- >>> scanr (-) 100 [1..4] -- [98,-97,99,-96,100] ---- --
-- >>> scanr (\nextChar reversedString -> nextChar : reversedString) "foo" ['a', 'b', 'c', 'd'] -- ["abcdfoo","bcdfoo","cdfoo","dfoo","foo"] ---- --
-- >>> force $ scanr (+) 0 [1..] -- *** Exception: stack overflow --scanr :: (a -> b -> b) -> b -> [a] -> [b] -- | <math>. scanr1 is a variant of scanr that has no -- starting value argument. -- --
-- >>> scanr1 (+) [1..4] -- [10,9,7,4] ---- --
-- >>> scanr1 (+) [] -- [] ---- --
-- >>> scanr1 (-) [1..4] -- [-2,3,-1,4] ---- --
-- >>> scanr1 (&&) [True, False, True, True] -- [False,False,True,True] ---- --
-- >>> scanr1 (||) [True, True, False, False] -- [True,True,False,False] ---- --
-- >>> force $ scanr1 (+) [1..] -- *** Exception: stack overflow --scanr1 :: (a -> a -> a) -> [a] -> [a] -- | iterate f x returns an infinite list of repeated -- applications of f to x: -- --
-- iterate f x == [x, f x, f (f x), ...] ---- --
-- >>> take 1 $ iterate undefined 42 -- [42] ---- --
-- >>> take 10 $ iterate not True -- [True,False,True,False,True,False,True,False,True,False] ---- --
-- >>> take 10 $ iterate (+3) 42 -- [42,45,48,51,54,57,60,63,66,69] ---- -- iterate id == repeat: -- --
-- >>> take 10 $ iterate id 1 -- [1,1,1,1,1,1,1,1,1,1] --iterate :: (a -> a) -> a -> [a] -- | replicate n x is a list of length n with -- x the value of every element. It is an instance of the more -- general genericReplicate, in which n may be of any -- integral type. -- --
-- >>> replicate 0 True -- [] ---- --
-- >>> replicate (-1) True -- [] ---- --
-- >>> replicate 4 True -- [True,True,True,True] --replicate :: Int -> a -> [a] -- | takeWhile, applied to a predicate p and a list -- xs, returns the longest prefix (possibly empty) of -- xs of elements that satisfy p. -- --
-- >>> takeWhile (const False) undefined -- *** Exception: Prelude.undefined ---- --
-- >>> takeWhile (const False) (undefined : undefined) -- [] ---- --
-- >>> take 1 (takeWhile (const True) (1 : undefined)) -- [1] ---- --
-- >>> takeWhile (< 3) [1,2,3,4,1,2,3,4] -- [1,2] ---- --
-- >>> takeWhile (< 9) [1,2,3] -- [1,2,3] ---- --
-- >>> takeWhile (< 0) [1,2,3] -- [] --takeWhile :: (a -> Bool) -> [a] -> [a] -- | dropWhile p xs returns the suffix remaining after -- takeWhile p xs. -- --
-- >>> dropWhile (< 3) [1,2,3,4,5,1,2,3] -- [3,4,5,1,2,3] ---- --
-- >>> dropWhile (< 9) [1,2,3] -- [] ---- --
-- >>> dropWhile (< 0) [1,2,3] -- [1,2,3] --dropWhile :: (a -> Bool) -> [a] -> [a] -- | take n, applied to a list xs, returns the -- prefix of xs of length n, or xs itself if -- n >= length xs. -- -- It is an instance of the more general genericTake, in which -- n may be of any integral type. -- --
-- >>> take 0 undefined -- [] -- -- >>> take 2 (1 : 2 : undefined) -- [1,2] ---- --
-- >>> take 5 "Hello World!" -- "Hello" ---- --
-- >>> take 3 [1,2,3,4,5] -- [1,2,3] ---- --
-- >>> take 3 [1,2] -- [1,2] ---- --
-- >>> take 3 [] -- [] ---- --
-- >>> take (-1) [1,2] -- [] ---- --
-- >>> take 0 [1,2] -- [] --take :: Int -> [a] -> [a] -- | drop n xs returns the suffix of xs after the -- first n elements, or [] if n >= length -- xs. -- -- It is an instance of the more general genericDrop, in which -- n may be of any integral type. -- --
-- >>> drop 6 "Hello World!" -- "World!" ---- --
-- >>> drop 3 [1,2,3,4,5] -- [4,5] ---- --
-- >>> drop 3 [1,2] -- [] ---- --
-- >>> drop 3 [] -- [] ---- --
-- >>> drop (-1) [1,2] -- [1,2] ---- --
-- >>> drop 0 [1,2] -- [1,2] --drop :: Int -> [a] -> [a] -- | splitAt n xs returns a tuple where first element is -- xs prefix of length n and second element is the -- remainder of the list: -- -- splitAt is an instance of the more general -- genericSplitAt, in which n may be of any integral -- type. -- --
-- >>> fst (splitAt 0 undefined) -- [] ---- --
-- >>> take 1 (fst (splitAt 10 (1 : undefined))) -- [1] ---- --
-- >>> splitAt 6 "Hello World!"
-- ("Hello ","World!")
--
--
-- -- >>> splitAt 3 [1,2,3,4,5] -- ([1,2,3],[4,5]) ---- --
-- >>> splitAt 1 [1,2,3] -- ([1],[2,3]) ---- --
-- >>> splitAt 3 [1,2,3] -- ([1,2,3],[]) ---- --
-- >>> splitAt 4 [1,2,3] -- ([1,2,3],[]) ---- --
-- >>> splitAt 0 [1,2,3] -- ([],[1,2,3]) ---- --
-- >>> splitAt (-1) [1,2,3] -- ([],[1,2,3]) --splitAt :: Int -> [a] -> ([a], [a]) -- | span, applied to a predicate p and a list xs, -- returns a tuple where first element is the longest prefix (possibly -- empty) of xs of elements that satisfy p and second -- element is the remainder of the list: -- -- span p xs is equivalent to (takeWhile p xs, -- dropWhile p xs), even if p is _|_. -- --
-- >>> span undefined [] -- ([],[]) -- -- >>> fst (span (const False) undefined) -- *** Exception: Prelude.undefined -- -- >>> fst (span (const False) (undefined : undefined)) -- [] -- -- >>> take 1 (fst (span (const True) (1 : undefined))) -- [1] ---- -- span produces the first component of the tuple lazily: -- --
-- >>> take 10 (fst (span (const True) [1..])) -- [1,2,3,4,5,6,7,8,9,10] ---- --
-- >>> span (< 3) [1,2,3,4,1,2,3,4] -- ([1,2],[3,4,1,2,3,4]) ---- --
-- >>> span (< 9) [1,2,3] -- ([1,2,3],[]) ---- --
-- >>> span (< 0) [1,2,3] -- ([],[1,2,3]) --span :: (a -> Bool) -> [a] -> ([a], [a]) -- | break, applied to a predicate p and a list -- xs, returns a tuple where first element is longest prefix -- (possibly empty) of xs of elements that do not satisfy -- p and second element is the remainder of the list: -- -- break p is equivalent to span (not . -- p) and consequently to (takeWhile (not . p) xs, -- dropWhile (not . p) xs), even if p is -- _|_. -- --
-- >>> break undefined [] -- ([],[]) ---- --
-- >>> fst (break (const True) undefined) -- *** Exception: Prelude.undefined ---- --
-- >>> fst (break (const True) (undefined : undefined)) -- [] ---- --
-- >>> take 1 (fst (break (const False) (1 : undefined))) -- [1] ---- -- break produces the first component of the tuple lazily: -- --
-- >>> take 10 (fst (break (const False) [1..])) -- [1,2,3,4,5,6,7,8,9,10] ---- --
-- >>> break (> 3) [1,2,3,4,1,2,3,4] -- ([1,2,3],[4,1,2,3,4]) ---- --
-- >>> break (< 9) [1,2,3] -- ([],[1,2,3]) ---- --
-- >>> break (> 9) [1,2,3] -- ([1,2,3],[]) --break :: (a -> Bool) -> [a] -> ([a], [a]) -- | <math>. reverse xs returns the elements of -- xs in reverse order. xs must be finite. -- --
-- >>> head (reverse [undefined, 1]) -- 1 ---- --
-- >>> reverse (1 : 2 : undefined) -- *** Exception: Prelude.undefined ---- --
-- >>> reverse [] -- [] ---- --
-- >>> reverse [42] -- [42] ---- --
-- >>> reverse [2,5,7] -- [7,5,2] ---- --
-- >>> reverse [1..] -- * Hangs forever * --reverse :: [a] -> [a] -- | and returns the conjunction of a container of Bools. For the -- result to be True, the container must be finite; False, -- however, results from a False value finitely far from the left -- end. -- --
-- >>> and [] -- True ---- --
-- >>> and [True] -- True ---- --
-- >>> and [False] -- False ---- --
-- >>> and [True, True, False] -- False ---- --
-- >>> and (False : repeat True) -- Infinite list [False,True,True,True,... -- False ---- --
-- >>> and (repeat True) -- * Hangs forever * --and :: Foldable t => t Bool -> Bool -- | or returns the disjunction of a container of Bools. For the -- result to be False, the container must be finite; True, -- however, results from a True value finitely far from the left -- end. -- --
-- >>> or [] -- False ---- --
-- >>> or [True] -- True ---- --
-- >>> or [False] -- False ---- --
-- >>> or [True, True, False] -- True ---- --
-- >>> or (True : repeat False) -- Infinite list [True,False,False,False,... -- True ---- --
-- >>> or (repeat False) -- * Hangs forever * --or :: Foldable t => t Bool -> Bool -- | Determines whether any element of the structure satisfies the -- predicate. -- --
-- >>> any (> 3) [] -- False ---- --
-- >>> any (> 3) [1,2] -- False ---- --
-- >>> any (> 3) [1,2,3,4,5] -- True ---- --
-- >>> any (> 3) [1..] -- True ---- --
-- >>> any (> 3) [0, -1..] -- * Hangs forever * --any :: Foldable t => (a -> Bool) -> t a -> Bool -- | Determines whether all elements of the structure satisfy the -- predicate. -- --
-- >>> all (> 3) [] -- True ---- --
-- >>> all (> 3) [1,2] -- False ---- --
-- >>> all (> 3) [1,2,3,4,5] -- False ---- --
-- >>> all (> 3) [1..] -- False ---- --
-- >>> all (> 3) [4..] -- * Hangs forever * --all :: Foldable t => (a -> Bool) -> t a -> Bool -- | notElem is the negation of elem. -- --
-- >>> 3 `notElem` [] -- True ---- --
-- >>> 3 `notElem` [1,2] -- True ---- --
-- >>> 3 `notElem` [1,2,3,4,5] -- False ---- -- For infinite structures, notElem terminates if the value exists -- at a finite distance from the left side of the structure: -- --
-- >>> 3 `notElem` [1..] -- False ---- --
-- >>> 3 `notElem` ([4..] ++ [3]) -- * Hangs forever * --notElem :: (Foldable t, Eq a) => a -> t a -> Bool infix 4 `notElem` -- | <math>. lookup key assocs looks up a key in an -- association list. For the result to be Nothing, the list must -- be finite. -- --
-- >>> lookup 2 [] -- Nothing ---- --
-- >>> lookup 2 [(1, "first")] -- Nothing ---- --
-- >>> lookup 2 [(1, "first"), (2, "second"), (3, "third")] -- Just "second" --lookup :: Eq a => a -> [(a, b)] -> Maybe b -- | Map a function over all the elements of a container and concatenate -- the resulting lists. -- --
-- >>> concatMap (take 3) [[1..], [10..], [100..], [1000..]] -- [1,2,3,10,11,12,100,101,102,1000,1001,1002] ---- --
-- >>> concatMap (take 3) (Just [1..]) -- [1,2,3] --concatMap :: Foldable t => (a -> [b]) -> t a -> [b] -- | List index (subscript) operator, starting from 0. It is an instance of -- the more general genericIndex, which takes an index of any -- integral type. -- -- WARNING: This function is partial, and should only be used if you are -- sure that the indexing will not fail. Otherwise, use !?. -- -- WARNING: This function takes linear time in the index. -- --
-- >>> ['a', 'b', 'c'] !! 0 -- 'a' ---- --
-- >>> ['a', 'b', 'c'] !! 2 -- 'c' ---- --
-- >>> ['a', 'b', 'c'] !! 3 -- *** Exception: Prelude.!!: index too large ---- --
-- >>> ['a', 'b', 'c'] !! (-1) -- *** Exception: Prelude.!!: negative index --(!!) :: HasCallStack => [a] -> Int -> a infixl 9 !! -- | zip3 takes three lists and returns a list of triples, analogous -- to zip. It is capable of list fusion, but it is restricted to -- its first list argument and its resulting list. zip3 :: [a] -> [b] -> [c] -> [(a, b, c)] -- | The unzip3 function takes a list of triples and returns three -- lists of the respective components, analogous to unzip. -- --
-- >>> unzip3 [] -- ([],[],[]) ---- --
-- >>> unzip3 [(1, 'a', True), (2, 'b', False)] -- ([1,2],"ab",[True,False]) --unzip3 :: [(a, b, c)] -> ([a], [b], [c]) -- | The shows functions return a function that prepends the -- output String to an existing String. This allows -- constant-time concatenation of results using function composition. type ShowS = String -> String -- | equivalent to showsPrec with a precedence of 0. shows :: Show a => a -> ShowS -- | utility function converting a Char to a show function that -- simply prepends the character unchanged. showChar :: Char -> ShowS -- | utility function converting a String to a show function that -- simply prepends the string unchanged. showString :: String -> ShowS -- | utility function that surrounds the inner show function with -- parentheses when the Bool parameter is True. showParen :: Bool -> ShowS -> ShowS odd :: Integral a => a -> Bool -- | raise a number to an integral power (^^) :: (Fractional a, Integral b) => a -> b -> a infixr 8 ^^ -- | gcd x y is the non-negative factor of both x -- and y of which every common factor of x and -- y is also a factor; for example gcd 4 2 = 2, -- gcd (-4) 6 = 2, gcd 0 4 = 4. -- gcd 0 0 = 0. (That is, the common divisor -- that is "greatest" in the divisibility preordering.) -- -- Note: Since for signed fixed-width integer types, abs -- minBound < 0, the result may be negative if one of the -- arguments is minBound (and necessarily is if the other -- is 0 or minBound) for such types. gcd :: Integral a => a -> a -> a -- | lcm x y is the smallest positive integer that both -- x and y divide. lcm :: Integral a => a -> a -> a -- | Extract the first component of a pair. fst :: (a, b) -> a -- | Extract the second component of a pair. snd :: (a, b) -> b -- | curry converts an uncurried function to a curried function. -- --
-- >>> curry fst 1 2 -- 1 --curry :: ((a, b) -> c) -> a -> b -> c -- | A parser for a type a, represented as a function that takes a -- String and returns a list of possible parses as -- (a,String) pairs. -- -- Note that this kind of backtracking parser is very inefficient; -- reading a large structure may be quite slow (cf ReadP). type ReadS a = String -> [(a, String)] -- | The lex function reads a single lexeme from the input, -- discarding initial white space, and returning the characters that -- constitute the lexeme. If the input string contains only white space, -- lex returns a single successful `lexeme' consisting of the -- empty string. (Thus lex "" = [("","")].) If there is -- no legal lexeme at the beginning of the input string, lex fails -- (i.e. returns []). -- -- This lexer is not completely faithful to the Haskell lexical syntax in -- the following respects: -- --
-- >>> let s = Left "foo" :: Either String Int -- -- >>> let n = Right 3 :: Either String Int -- -- >>> either length (*2) s -- 3 -- -- >>> either length (*2) n -- 6 --either :: (a -> c) -> (b -> c) -> Either a b -> c -- | equivalent to readsPrec with a precedence of 0. reads :: Read a => ReadS a -- | The read function reads input from a string, which must be -- completely consumed by the input process. read fails with an -- error if the parse is unsuccessful, and it is therefore -- discouraged from being used in real applications. Use readMaybe -- or readEither for safe alternatives. -- --
-- >>> read "123" :: Int -- 123 ---- --
-- >>> read "hello" :: Int -- *** Exception: Prelude.read: no parse --read :: Read a => String -> a -- | Splits the argument into a list of lines stripped of their -- terminating \n characters. The \n terminator is -- optional in a final non-empty line of the argument string. -- -- When the argument string is empty, or ends in a \n character, -- it can be recovered by passing the result of lines to the -- unlines function. Otherwise, unlines appends the missing -- terminating \n. This makes unlines . lines -- idempotent: -- --
-- (unlines . lines) . (unlines . lines) = (unlines . lines) ---- --
-- >>> lines "" -- empty input contains no lines -- [] ---- --
-- >>> lines "\n" -- single empty line -- [""] ---- --
-- >>> lines "one" -- single unterminated line -- ["one"] ---- --
-- >>> lines "one\n" -- single non-empty line -- ["one"] ---- --
-- >>> lines "one\n\n" -- second line is empty -- ["one",""] ---- --
-- >>> lines "one\ntwo" -- second line is unterminated -- ["one","two"] ---- --
-- >>> lines "one\ntwo\n" -- two non-empty lines -- ["one","two"] --lines :: String -> [String] -- | Appends a \n character to each input string, then -- concatenates the results. Equivalent to foldMap (s -> -- s ++ "\n"). -- --
-- >>> unlines ["Hello", "World", "!"] -- "Hello\nWorld\n!\n" ---- -- Note that unlines . lines /= -- id when the input is not \n-terminated: -- --
-- >>> unlines . lines $ "foo\nbar" -- "foo\nbar\n" --unlines :: [String] -> String -- | words breaks a string up into a list of words, which were -- delimited by white space (as defined by isSpace). This function -- trims any white spaces at the beginning and at the end. -- --
-- >>> words "Lorem ipsum\ndolor" -- ["Lorem","ipsum","dolor"] ---- --
-- >>> words " foo bar " -- ["foo","bar"] --words :: String -> [String] -- | unwords joins words with separating spaces (U+0020 SPACE). -- -- unwords is neither left nor right inverse of words: -- --
-- >>> words (unwords [" "]) -- [] -- -- >>> unwords (words "foo\nbar") -- "foo bar" ---- --
-- >>> unwords ["Lorem", "ipsum", "dolor"] -- "Lorem ipsum dolor" ---- --
-- >>> unwords ["foo", "bar", "", "baz"] -- "foo bar baz" --unwords :: [String] -> String -- | Construct an IOError value with a string describing the error. -- The fail method of the IO instance of the Monad -- class raises a userError, thus: -- --
-- instance Monad IO where -- ... -- fail s = ioError (userError s) --userError :: String -> IOError -- | File and directory names are values of type String, whose -- precise meaning is operating system dependent. Files can be opened, -- yielding a handle which can then be used to operate on the contents of -- that file. type FilePath = String -- | Raise an IOError in the IO monad. ioError :: IOError -> IO a -- | Write a character to the standard output device (same as -- hPutChar stdout). putChar :: Char -> IO () -- | Write a string to the standard output device (same as hPutStr -- stdout). putStr :: String -> IO () -- | Read a character from the standard input device (same as -- hGetChar stdin). getChar :: IO Char -- | The getContents operation returns all user input as a single -- string, which is read lazily as it is needed (same as -- hGetContents stdin). getContents :: IO String -- | The interact function takes a function of type -- String->String as its argument. The entire input from the -- standard input device is passed to this function as its argument, and -- the resulting string is output on the standard output device. interact :: (String -> String) -> IO () -- | The readFile function reads a file and returns the contents of -- the file as a string. The file is read lazily, on demand, as with -- getContents. readFile :: FilePath -> IO String -- | The computation appendFile file str function appends -- the string str, to the file file. -- -- Note that writeFile and appendFile write a literal -- string to a file. To write a value of any printable type, as with -- print, use the show function to convert the value to a -- string first. -- --
-- main = appendFile "squares" (show [(x,x*x) | x <- [0,0.1..2]]) --appendFile :: FilePath -> String -> IO () -- | The readLn function combines getLine and readIO. readLn :: Read a => IO a -- | The readIO function is similar to read except that it -- signals parse failure to the IO monad instead of terminating -- the program. readIO :: Read a => String -> IO a module Hedgehog.Internal.Range -- | Tests are parameterized by the size of the randomly-generated data. -- The meaning of a Size value depends on the particular generator -- used, but it must always be a number between 0 and 99 inclusive. newtype Size Size :: Int -> Size [unSize] :: Size -> Int -- | A range describes the bounds of a number to generate, which may or may -- not be dependent on a Size. -- -- The constructor takes an origin between the lower and upper bound, and -- a function from Size to bounds. As the size goes towards -- 0, the values go towards the origin. data Range a Range :: !a -> (Size -> (a, a)) -> Range a -- | Get the origin of a range. This might be the mid-point or the lower -- bound, depending on what the range represents. -- -- The bounds of a range are scaled around this value when using -- the linear family of combinators. -- -- When using a Range to generate numbers, the shrinking function -- will shrink towards the origin. origin :: Range a -> a -- | Get the extents of a range, for a given size. bounds :: Size -> Range a -> (a, a) -- | Get the lower bound of a range for the given size. lowerBound :: Ord a => Size -> Range a -> a -- | Get the upper bound of a range for the given size. upperBound :: Ord a => Size -> Range a -> a -- | Construct a range which represents a constant single value. -- --
-- >>> bounds x $ singleton 5 -- (5,5) ---- --
-- >>> origin $ singleton 5 -- 5 --singleton :: a -> Range a -- | Construct a range which is unaffected by the size parameter. -- -- A range from 0 to 10, with the origin at 0: -- --
-- >>> bounds x $ constant 0 10 -- (0,10) ---- --
-- >>> origin $ constant 0 10 -- 0 --constant :: a -> a -> Range a -- | Construct a range which is unaffected by the size parameter with a -- origin point which may differ from the bounds. -- -- A range from -10 to 10, with the origin at -- 0: -- --
-- >>> bounds x $ constantFrom 0 (-10) 10 -- (-10,10) ---- --
-- >>> origin $ constantFrom 0 (-10) 10 -- 0 ---- -- A range from 1970 to 2100, with the origin at -- 2000: -- --
-- >>> bounds x $ constantFrom 2000 1970 2100 -- (1970,2100) ---- --
-- >>> origin $ constantFrom 2000 1970 2100 -- 2000 --constantFrom :: a -> a -> a -> Range a -- | Construct a range which is unaffected by the size parameter using the -- full range of a data type. -- -- A range from -128 to 127, with the origin at -- 0: -- --
-- >>> bounds x (constantBounded :: Range Int8) -- (-128,127) ---- --
-- >>> origin (constantBounded :: Range Int8) -- 0 --constantBounded :: (Bounded a, Num a) => Range a -- | Construct a range which scales the second bound relative to the size -- parameter. -- --
-- >>> bounds 0 $ linear 0 10 -- (0,0) ---- --
-- >>> bounds 50 $ linear 0 10 -- (0,5) ---- --
-- >>> bounds 99 $ linear 0 10 -- (0,10) --linear :: Integral a => a -> a -> Range a -- | Construct a range which scales the bounds relative to the size -- parameter. -- --
-- >>> bounds 0 $ linearFrom 0 (-10) 10 -- (0,0) ---- --
-- >>> bounds 50 $ linearFrom 0 (-10) 20 -- (-5,10) ---- --
-- >>> bounds 99 $ linearFrom 0 (-10) 20 -- (-10,20) --linearFrom :: Integral a => a -> a -> a -> Range a -- | Construct a range which scales the second bound relative to the size -- parameter. -- -- This works the same as linear, but for fractional -- values. linearFrac :: (Fractional a, Ord a) => a -> a -> Range a -- | Construct a range which scales the bounds relative to the size -- parameter. -- -- This works the same as linearFrom, but for fractional -- values. linearFracFrom :: (Fractional a, Ord a) => a -> a -> a -> Range a -- | Construct a range which is scaled relative to the size parameter and -- uses the full range of a data type. -- --
-- >>> bounds 0 (linearBounded :: Range Int8) -- (0,0) ---- --
-- >>> bounds 50 (linearBounded :: Range Int8) -- (-64,64) ---- --
-- >>> bounds 99 (linearBounded :: Range Int8) -- (-128,127) --linearBounded :: (Bounded a, Integral a) => Range a -- | Construct a range which scales the second bound exponentially relative -- to the size parameter. -- --
-- >>> bounds 0 $ exponential 1 512 -- (1,1) ---- --
-- >>> bounds 11 $ exponential 1 512 -- (1,2) ---- --
-- >>> bounds 22 $ exponential 1 512 -- (1,4) ---- --
-- >>> bounds 77 $ exponential 1 512 -- (1,128) ---- --
-- >>> bounds 88 $ exponential 1 512 -- (1,256) ---- --
-- >>> bounds 99 $ exponential 1 512 -- (1,512) --exponential :: Integral a => a -> a -> Range a -- | Construct a range which scales the bounds exponentially relative to -- the size parameter. -- --
-- >>> bounds 0 $ exponentialFrom 0 (-128) 512 -- (0,0) ---- --
-- >>> bounds 25 $ exponentialFrom 0 (-128) 512 -- (-2,4) ---- --
-- >>> bounds 50 $ exponentialFrom 0 (-128) 512 -- (-11,22) ---- --
-- >>> bounds 75 $ exponentialFrom 0 (-128) 512 -- (-39,112) ---- --
-- >>> bounds 99 $ exponentialFrom x (-128) 512 -- (-128,512) --exponentialFrom :: Integral a => a -> a -> a -> Range a -- | Construct a range which is scaled exponentially relative to the size -- parameter and uses the full range of a data type. -- --
-- >>> bounds 0 (exponentialBounded :: Range Int8) -- (0,0) ---- --
-- >>> bounds 50 (exponentialBounded :: Range Int8) -- (-11,11) ---- --
-- >>> bounds 99 (exponentialBounded :: Range Int8) -- (-128,127) --exponentialBounded :: (Bounded a, Integral a) => Range a -- | Construct a range which scales the second bound exponentially relative -- to the size parameter. -- -- This works the same as exponential, but for floating-point -- values. -- --
-- >>> bounds 0 $ exponentialFloat 0 10 -- (0.0,0.0) ---- --
-- >>> bounds 50 $ exponentialFloat 0 10 -- (0.0,2.357035250656098) ---- --
-- >>> bounds 99 $ exponentialFloat 0 10 -- (0.0,10.0) --exponentialFloat :: (Floating a, Ord a) => a -> a -> Range a -- | Construct a range which scales the bounds exponentially relative to -- the size parameter. -- -- This works the same as exponentialFrom, but for -- floating-point values. -- --
-- >>> bounds 0 $ exponentialFloatFrom 0 (-10) 20 -- (0.0,0.0) ---- --
-- >>> bounds 50 $ exponentialFloatFrom 0 (-10) 20 -- (-2.357035250656098,3.6535836249197002) ---- --
-- >>> bounds 99 $ exponentialFloatFrom x (-10) 20 -- (-10.0,20.0) --exponentialFloatFrom :: (Floating a, Ord a) => a -> a -> a -> Range a -- | Truncate a value so it stays within some range. -- --
-- >>> clamp 5 10 15 -- 10 ---- --
-- >>> clamp 5 10 0 -- 5 --clamp :: Ord a => a -> a -> a -> a -- | Scale an integral linearly with the size parameter. scaleLinear :: Integral a => Size -> a -> a -> a -- | Scale a fractional number linearly with the size parameter. scaleLinearFrac :: Fractional a => Size -> a -> a -> a -- | Scale an integral exponentially with the size parameter. scaleExponential :: Integral a => Size -> a -> a -> a -- | Scale a floating-point number exponentially with the size parameter. scaleExponentialFloat :: Floating a => Size -> a -> a -> a instance GHC.Enum.Enum Hedgehog.Internal.Range.Size instance GHC.Classes.Eq Hedgehog.Internal.Range.Size instance GHC.Base.Functor Hedgehog.Internal.Range.Range instance GHC.Real.Integral Hedgehog.Internal.Range.Size instance GHC.Num.Num Hedgehog.Internal.Range.Size instance GHC.Classes.Ord Hedgehog.Internal.Range.Size instance GHC.Read.Read Hedgehog.Internal.Range.Size instance GHC.Real.Real Hedgehog.Internal.Range.Size instance GHC.Show.Show Hedgehog.Internal.Range.Size module Hedgehog.Internal.Region newtype Region Region :: TVar Body -> Region [unRegion] :: Region -> TVar Body newEmptyRegion :: LiftRegion m => m Region newOpenRegion :: LiftRegion m => m Region openRegion :: LiftRegion m => Region -> String -> m () setRegion :: LiftRegion m => Region -> String -> m () displayRegions :: (MonadIO m, MonadMask m) => m a -> m a displayRegion :: (MonadIO m, MonadMask m, LiftRegion m) => (Region -> m a) -> m a moveToBottom :: Region -> STM () finishRegion :: LiftRegion m => Region -> m () -- | This is a port of "Fast Splittable Pseudorandom Number Generators" by -- Steele et. al. [1]. -- -- The paper's algorithm provides decent randomness for most purposes but -- sacrifices cryptographic-quality randomness in favor of speed. The -- original implementation is tested with DieHarder and BigCrush; see the -- paper for details. -- -- This implementation, originally from [2], is a port from the paper. -- -- It also takes in to account the SplittableRandom.java source code in -- OpenJDK v8u40-b25 as well as splittable_random.ml in Jane Street's -- standard library overlay (kernel) v113.33.03, and Random.fs in FsCheck -- v3. -- -- Other than the choice of initial seed for from this port should -- be faithful. -- --
-- >>> towards 0 100 -- [0,50,75,88,94,97,99] ---- --
-- >>> towards 500 1000 -- [500,750,875,938,969,985,993,997,999] ---- --
-- >>> towards (-50) (-26) -- [-50,-38,-32,-29,-27] ---- -- Note we always try the destination first, as that is the optimal -- shrink. towards :: Integral a => a -> a -> [a] -- | Shrink a floating-point number by edging towards a destination. -- --
-- >>> take 7 (towardsFloat 0.0 100) -- [0.0,50.0,75.0,87.5,93.75,96.875,98.4375] ---- --
-- >>> take 7 (towardsFloat 1.0 0.5) -- [1.0,0.75,0.625,0.5625,0.53125,0.515625,0.5078125] ---- -- Note we always try the destination first, as that is the optimal -- shrink. towardsFloat :: RealFloat a => a -> a -> [a] -- | Shrink a list by edging towards the empty list. -- --
-- >>> list [1,2,3] -- [[],[2,3],[1,3],[1,2]] ---- --
-- >>> list "abcd" -- ["","cd","ab","bcd","acd","abd","abc"] ---- -- Note we always try the empty list first, as that is the optimal -- shrink. list :: [a] -> [[a]] -- | Produce a list containing the progressive halving of an integral. -- --
-- >>> halves 15 -- [15,7,3,1] ---- --
-- >>> halves 100 -- [100,50,25,12,6,3,1] ---- --
-- >>> halves (-26) -- [-26,-13,-6,-3,-1] --halves :: Integral a => a -> [a] -- | Produce all permutations of removing k elements from a list. -- --
-- >>> removes 2 "abcdef" -- ["cdef","abef","abcd"] --removes :: Int -> [a] -> [[a]] -- | Cons an element on to the front of a list unless it is already there. consNub :: Eq a => a -> [a] -> [a] module Hedgehog.Internal.Source newtype LineNo LineNo :: Int -> LineNo [unLineNo] :: LineNo -> Int newtype ColumnNo ColumnNo :: Int -> ColumnNo [unColumnNo] :: ColumnNo -> Int data Span Span :: !FilePath -> !LineNo -> !ColumnNo -> !LineNo -> !ColumnNo -> Span [spanFile] :: Span -> !FilePath [spanStartLine] :: Span -> !LineNo [spanStartColumn] :: Span -> !ColumnNo [spanEndLine] :: Span -> !LineNo [spanEndColumn] :: Span -> !ColumnNo getCaller :: CallStack -> Maybe Span -- | CallStacks are a lightweight method of obtaining a partial -- call-stack at any point in the program. -- -- A function can request its call-site with the HasCallStack -- constraint. For example, we can define -- --
-- putStrLnWithCallStack :: HasCallStack => String -> IO () ---- -- as a variant of putStrLn that will get its call-site and -- print it, along with the string given as argument. We can access the -- call-stack inside putStrLnWithCallStack with -- callStack. -- --
-- >>> :{
-- putStrLnWithCallStack :: HasCallStack => String -> IO ()
-- putStrLnWithCallStack msg = do
-- putStrLn msg
-- putStrLn (prettyCallStack callStack)
-- :}
--
--
-- Thus, if we call putStrLnWithCallStack we will get a
-- formatted call-stack alongside our string.
--
-- -- >>> putStrLnWithCallStack "hello" -- hello -- CallStack (from HasCallStack): -- putStrLnWithCallStack, called at <interactive>:... in interactive:Ghci... ---- -- GHC solves HasCallStack constraints in three steps: -- --
-- >>> bounds x $ singleton 5 -- (5,5) ---- --
-- >>> origin $ singleton 5 -- 5 --singleton :: a -> Range a -- | Construct a range which is unaffected by the size parameter. -- -- A range from 0 to 10, with the origin at 0: -- --
-- >>> bounds x $ constant 0 10 -- (0,10) ---- --
-- >>> origin $ constant 0 10 -- 0 --constant :: a -> a -> Range a -- | Construct a range which is unaffected by the size parameter with a -- origin point which may differ from the bounds. -- -- A range from -10 to 10, with the origin at -- 0: -- --
-- >>> bounds x $ constantFrom 0 (-10) 10 -- (-10,10) ---- --
-- >>> origin $ constantFrom 0 (-10) 10 -- 0 ---- -- A range from 1970 to 2100, with the origin at -- 2000: -- --
-- >>> bounds x $ constantFrom 2000 1970 2100 -- (1970,2100) ---- --
-- >>> origin $ constantFrom 2000 1970 2100 -- 2000 --constantFrom :: a -> a -> a -> Range a -- | Construct a range which is unaffected by the size parameter using the -- full range of a data type. -- -- A range from -128 to 127, with the origin at -- 0: -- --
-- >>> bounds x (constantBounded :: Range Int8) -- (-128,127) ---- --
-- >>> origin (constantBounded :: Range Int8) -- 0 --constantBounded :: (Bounded a, Num a) => Range a -- | Construct a range which scales the second bound relative to the size -- parameter. -- --
-- >>> bounds 0 $ linear 0 10 -- (0,0) ---- --
-- >>> bounds 50 $ linear 0 10 -- (0,5) ---- --
-- >>> bounds 99 $ linear 0 10 -- (0,10) --linear :: Integral a => a -> a -> Range a -- | Construct a range which scales the bounds relative to the size -- parameter. -- --
-- >>> bounds 0 $ linearFrom 0 (-10) 10 -- (0,0) ---- --
-- >>> bounds 50 $ linearFrom 0 (-10) 20 -- (-5,10) ---- --
-- >>> bounds 99 $ linearFrom 0 (-10) 20 -- (-10,20) --linearFrom :: Integral a => a -> a -> a -> Range a -- | Construct a range which scales the second bound relative to the size -- parameter. -- -- This works the same as linear, but for fractional -- values. linearFrac :: (Fractional a, Ord a) => a -> a -> Range a -- | Construct a range which scales the bounds relative to the size -- parameter. -- -- This works the same as linearFrom, but for fractional -- values. linearFracFrom :: (Fractional a, Ord a) => a -> a -> a -> Range a -- | Construct a range which is scaled relative to the size parameter and -- uses the full range of a data type. -- --
-- >>> bounds 0 (linearBounded :: Range Int8) -- (0,0) ---- --
-- >>> bounds 50 (linearBounded :: Range Int8) -- (-64,64) ---- --
-- >>> bounds 99 (linearBounded :: Range Int8) -- (-128,127) --linearBounded :: (Bounded a, Integral a) => Range a -- | Construct a range which scales the second bound exponentially relative -- to the size parameter. -- --
-- >>> bounds 0 $ exponential 1 512 -- (1,1) ---- --
-- >>> bounds 11 $ exponential 1 512 -- (1,2) ---- --
-- >>> bounds 22 $ exponential 1 512 -- (1,4) ---- --
-- >>> bounds 77 $ exponential 1 512 -- (1,128) ---- --
-- >>> bounds 88 $ exponential 1 512 -- (1,256) ---- --
-- >>> bounds 99 $ exponential 1 512 -- (1,512) --exponential :: Integral a => a -> a -> Range a -- | Construct a range which scales the bounds exponentially relative to -- the size parameter. -- --
-- >>> bounds 0 $ exponentialFrom 0 (-128) 512 -- (0,0) ---- --
-- >>> bounds 25 $ exponentialFrom 0 (-128) 512 -- (-2,4) ---- --
-- >>> bounds 50 $ exponentialFrom 0 (-128) 512 -- (-11,22) ---- --
-- >>> bounds 75 $ exponentialFrom 0 (-128) 512 -- (-39,112) ---- --
-- >>> bounds 99 $ exponentialFrom x (-128) 512 -- (-128,512) --exponentialFrom :: Integral a => a -> a -> a -> Range a -- | Construct a range which is scaled exponentially relative to the size -- parameter and uses the full range of a data type. -- --
-- >>> bounds 0 (exponentialBounded :: Range Int8) -- (0,0) ---- --
-- >>> bounds 50 (exponentialBounded :: Range Int8) -- (-11,11) ---- --
-- >>> bounds 99 (exponentialBounded :: Range Int8) -- (-128,127) --exponentialBounded :: (Bounded a, Integral a) => Range a -- | Construct a range which scales the second bound exponentially relative -- to the size parameter. -- -- This works the same as exponential, but for floating-point -- values. -- --
-- >>> bounds 0 $ exponentialFloat 0 10 -- (0.0,0.0) ---- --
-- >>> bounds 50 $ exponentialFloat 0 10 -- (0.0,2.357035250656098) ---- --
-- >>> bounds 99 $ exponentialFloat 0 10 -- (0.0,10.0) --exponentialFloat :: (Floating a, Ord a) => a -> a -> Range a -- | Construct a range which scales the bounds exponentially relative to -- the size parameter. -- -- This works the same as exponentialFrom, but for -- floating-point values. -- --
-- >>> bounds 0 $ exponentialFloatFrom 0 (-10) 20 -- (0.0,0.0) ---- --
-- >>> bounds 50 $ exponentialFloatFrom 0 (-10) 20 -- (-2.357035250656098,3.6535836249197002) ---- --
-- >>> bounds 99 $ exponentialFloatFrom x (-10) 20 -- (-10.0,20.0) --exponentialFloatFrom :: (Floating a, Ord a) => a -> a -> a -> Range a module Hedgehog.Internal.Gen -- | Generator for random values of a. type Gen = GenT Identity -- | Monad transformer which can generate random values of a. newtype GenT (m :: Type -> Type) a GenT :: (Size -> Seed -> TreeT (MaybeT m) a) -> GenT (m :: Type -> Type) a [unGenT] :: GenT (m :: Type -> Type) a -> Size -> Seed -> TreeT (MaybeT m) a -- | Class of monads which can generate input data for tests. class (Monad m, Monad GenBase m) => MonadGen (m :: Type -> Type) where { type GenBase (m :: Type -> Type) :: Type -> Type; } -- | Extract a GenT from a MonadGen. toGenT :: MonadGen m => m a -> GenT (GenBase m) a -- | Lift a GenT in to a MonadGen. fromGenT :: MonadGen m => GenT (GenBase m) a -> m a -- | Lift a Gen / GenT Identity in to a Monad m => GenT -- m generalize :: forall (m :: Type -> Type) a. Monad m => Gen a -> GenT m a -- | Apply a shrinking function to a generator. -- -- This will give the generator additional shrinking options, while -- keeping the existing shrinks intact. shrink :: MonadGen m => (a -> [a]) -> m a -> m a -- | Throw away a generator's shrink tree. prune :: MonadGen m => m a -> m a -- | Make a generator smaller by scaling its size parameter. small :: MonadGen m => m a -> m a -- | Adjust the size parameter by transforming it with the given function. scale :: (HasCallStack, MonadGen m) => (Size -> Size) -> m a -> m a -- | Override the size parameter. Returns a generator which uses the given -- size instead of the runtime-size parameter. resize :: MonadGen m => Size -> m a -> m a -- | Construct a generator that depends on the size parameter. sized :: MonadGen m => (Size -> m a) -> m a -- | Generates a random integral number in the given -- [inclusive,inclusive] range. -- -- When the generator tries to shrink, it will shrink towards the -- origin of the specified Range. -- -- For example, the following generator will produce a number between -- 1970 and 2100, but will shrink towards -- 2000: -- --
-- integral (Range.constantFrom 2000 1970 2100) :: Gen Int ---- -- Some sample outputs from this generator might look like: -- --
-- === Outcome === -- 1973 -- === Shrinks === -- 2000 -- 1987 -- 1980 -- 1976 -- 1974 ---- --
-- === Outcome === -- 2061 -- === Shrinks === -- 2000 -- 2031 -- 2046 -- 2054 -- 2058 -- 2060 --integral :: (MonadGen m, Integral a) => Range a -> m a -- | Generates a random integral number in the [inclusive,inclusive] range. -- -- This generator does not shrink. integral_ :: (MonadGen m, Integral a) => Range a -> m a -- | Generates a random machine integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int :: MonadGen m => Range Int -> m Int -- | Generates a random 8-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int8 :: MonadGen m => Range Int8 -> m Int8 -- | Generates a random 16-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int16 :: MonadGen m => Range Int16 -> m Int16 -- | Generates a random 32-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int32 :: MonadGen m => Range Int32 -> m Int32 -- | Generates a random 64-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int64 :: MonadGen m => Range Int64 -> m Int64 -- | Generates a random machine word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word :: MonadGen m => Range Word -> m Word -- | Generates a random byte in the given [inclusive,inclusive] -- range. -- -- This is a specialization of integral, offered for -- convenience. word8 :: MonadGen m => Range Word8 -> m Word8 -- | Generates a random 16-bit word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word16 :: MonadGen m => Range Word16 -> m Word16 -- | Generates a random 32-bit word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word32 :: MonadGen m => Range Word32 -> m Word32 -- | Generates a random 64-bit word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word64 :: MonadGen m => Range Word64 -> m Word64 -- | Generates a random floating-point number in the -- [inclusive,exclusive) range. -- -- This generator works the same as integral, but for floating -- point numbers. realFloat :: (MonadGen m, RealFloat a) => Range a -> m a -- | Generates a random fractional number in the [inclusive,exclusive) -- range. -- -- This generator does not shrink. realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a -- | Generates a random floating-point number in the -- [inclusive,exclusive) range. -- -- This is a specialization of realFloat, offered for -- convenience. float :: MonadGen m => Range Float -> m Float -- | Generates a random floating-point number in the -- [inclusive,exclusive) range. -- -- This is a specialization of realFloat, offered for -- convenience. double :: MonadGen m => Range Double -> m Double -- | Generates an element from an enumeration. -- -- This generator shrinks towards the first argument. -- -- For example: -- --
-- enum 'a' 'z' :: Gen Char --enum :: (MonadGen m, Enum a) => a -> a -> m a -- | Generates a random value from a bounded enumeration. -- -- This generator shrinks towards minBound. -- -- For example: -- --
-- enumBounded :: Gen Bool ---- -- This is implemented in terms of the Enum class, and thus may -- be partial for integral types larger than Int, e.g. -- Word64. enumBounded :: (MonadGen m, Enum a, Bounded a) => m a -- | Generates a random boolean. -- -- This generator shrinks to False. -- -- This is a specialization of enumBounded, offered for -- convenience. bool :: MonadGen m => m Bool -- | Generates a random boolean. -- -- This generator does not shrink. bool_ :: MonadGen m => m Bool -- | Generates an ASCII binit: '0'..'1' binit :: MonadGen m => m Char -- | Generates an ASCII octit: '0'..'7' octit :: MonadGen m => m Char -- | Generates an ASCII digit: '0'..'9' digit :: MonadGen m => m Char -- | Generates an ASCII hexit: '0'..'9', 'a'..'f', 'A'..'F' hexit :: MonadGen m => m Char -- | Generates an ASCII lowercase letter: 'a'..'z' lower :: MonadGen m => m Char -- | Generates an ASCII uppercase letter: 'A'..'Z' upper :: MonadGen m => m Char -- | Generates an ASCII letter: 'a'..'z', 'A'..'Z' alpha :: MonadGen m => m Char -- | Generates an ASCII letter or digit: 'a'..'z', 'A'..'Z', -- '0'..'9' alphaNum :: MonadGen m => m Char -- | Generates an ASCII character: '0'..'127' ascii :: MonadGen m => m Char -- | Generates a Latin-1 character: '0'..'255' latin1 :: MonadGen m => m Char -- | Generates a Unicode character, excluding noncharacters and invalid -- standalone surrogates: '0'..'1114111' (excluding '55296'..'57343', -- '65534', '65535') unicode :: MonadGen m => m Char -- | Generates a Unicode character, including noncharacters and invalid -- standalone surrogates: '0'..'1114111' unicodeAll :: MonadGen m => m Char -- | Generates a string using Range to determine the length. -- -- This is a specialization of list, offered for -- convenience. string :: MonadGen m => Range Int -> m Char -> m String -- | Generates a string using Range to determine the length. text :: MonadGen m => Range Int -> m Char -> m Text -- | Generates a UTF-8 encoded string, using Range to determine the -- length. utf8 :: MonadGen m => Range Int -> m Char -> m ByteString -- | Generates a random ByteString, using Range to determine -- the length. bytes :: MonadGen m => Range Int -> m ByteString -- | Trivial generator that always produces the same element. -- -- This is another name for pure / return. constant :: MonadGen m => a -> m a -- | Randomly selects one of the elements in the list. -- -- This generator shrinks towards the first element in the list. -- -- The input list must be non-empty. element :: (HasCallStack, Foldable f, MonadGen m) => f a -> m a -- | Randomly selects one of the elements in the list. -- -- This generator does not shrink the choice of element. -- -- The input list must be non-empty. element_ :: (HasCallStack, MonadGen m) => [a] -> m a -- | Randomly selects one of the generators in the list. -- -- This generator shrinks towards the first generator in the list. -- -- The input list must be non-empty. choice :: (HasCallStack, MonadGen m) => [m a] -> m a -- | Uses a weighted distribution to randomly select one of the generators -- in the list. -- -- This generator shrinks towards the first generator in the list. -- -- The input list must be non-empty. frequency :: (HasCallStack, MonadGen m) => [(Int, m a)] -> m a -- | Modifies combinators which choose from a list of generators, like -- choice or frequency, so that they can be used in -- recursive scenarios. -- -- This combinator modifies its target to select one of the generators in -- either the non-recursive or the recursive list. When a selection is -- made from the recursive list, the Size is halved. When the -- Size gets to one or less, selections are no longer made from -- the recursive list, this ensures termination. -- -- A good example of where this might be useful is abstract syntax trees: -- --
-- data Expr = -- Var String -- | Lam String Expr -- | App Expr Expr -- -- -- Assuming we have a name generator -- genName :: MonadGen m => m String -- -- -- We can write a generator for expressions -- genExpr :: MonadGen m => m Expr -- genExpr = -- Gen.recursive Gen.choice [ -- -- non-recursive generators -- Var <$> genName -- ] [ -- -- recursive generators -- Gen.subtermM genExpr (x -> Lam <$> genName <*> pure x) -- , Gen.subterm2 genExpr genExpr App -- ] ---- -- If we wrote the above example using only choice, it is likely -- that it would fail to terminate. This is because for every call to -- genExpr, there is a 2 in 3 chance that we will recurse again. recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a -- | Discards the whole generator. discard :: MonadGen m => m a -- | Discards the generator if the generated value does not satisfy the -- predicate. ensure :: MonadGen m => (a -> Bool) -> m a -> m a -- | Generates a value that satisfies a predicate. -- -- Shrinks of the generated value will also satisfy the predicate. From -- the original generator's shrink tree, any values that fail the -- predicate will be removed, but any subsequent shrinks that satisfy it -- will be retained. Compared to filter, shrinking may be slower -- but will be optimal. -- -- It's possible that the predicate will never pass, or will only pass at -- a larger size than we're currently running at. To avoid looping -- forever, we limit the number of retries, and grow the size with each -- retry. If we retry too many times then the whole generator is -- discarded. filter :: (MonadGen m, GenBase m ~ Identity) => (a -> Bool) -> m a -> m a -- | Generates a value which is the result of the given function returning -- a Just. -- -- The original generator's shrink tree will be retained, with values -- returning Nothing removed. Subsequent shrinks of those values -- will be retained. Compared to mapMaybeT, shrinking may be -- slower but will be optimal. -- -- It's possible that the function will never return Just, or will -- only do so a larger size than we're currently running at. To avoid -- looping forever, we limit the number of retries, and grow the size -- with each retry. If we retry too many times then the whole generator -- is discarded. mapMaybe :: (MonadGen m, GenBase m ~ Identity) => (a -> Maybe b) -> m a -> m b -- | Generates a value that satisfies a predicate. -- -- Shrinks of the generated value will also satisfy the predicate. From -- the original generator's shrink tree, any values that fail the -- predicate will be removed, along with their subsequent shrinks. -- Compared to filter, shrinking may be faster but may also be -- less optimal. -- -- The type is also more general, because the shrink behavior from -- filter would force the entire shrink tree to be evaluated when -- applied to an impure tree. -- -- This is essentially: -- --
-- filterT p gen = mfilter p gen <|> filterT p gen ---- -- But that could loop forever, if the predicate will never pass or will -- only pass at a larger size than we're currently running at. We differ -- from the above in keeping some state to avoid that. We limit the -- number of retries, and grow the size with each retry. If we retry too -- many times then the whole generator is discarded. filterT :: MonadGen m => (a -> Bool) -> m a -> m a -- | Generates a value which is the result of the given function returning -- a Just. -- -- The original generator's shrink tree will be retained, with values -- returning Nothing removed. Subsequent shrinks of those values -- will be retained. Compared to mapMaybeT, shrinking may be -- slower but will be optimal. -- -- The type is also more general, because the shrink behavior from -- mapMaybe would force the entire shrink tree to be evaluated -- when applied to an impure tree. -- -- It's possible that the function will never return Just, or will -- only do so a larger size than we're currently running at. To avoid -- looping forever, we limit the number of retries, and grow the size -- with each retry. If we retry too many times then the whole generator -- is discarded. mapMaybeT :: MonadGen m => (a -> Maybe b) -> m a -> m b -- | Runs a Maybe generator until it produces a Just. -- -- This is implemented using filter and has the same -- caveats. just :: (MonadGen m, GenBase m ~ Identity) => m (Maybe a) -> m a -- | Runs a Maybe generator until it produces a Just. -- -- This is implemented using filter and has the same -- caveats. justT :: MonadGen m => m (Maybe a) -> m a -- | Generates a Nothing some of the time. maybe :: MonadGen m => m a -> m (Maybe a) -- | Generates either an a or a b. -- -- As the size grows, this generator generates Rights more often -- than Lefts. either :: MonadGen m => m a -> m b -> m (Either a b) -- | Generates either an a or a b, without bias. -- -- This generator generates as many Rights as it does -- Lefts. either_ :: MonadGen m => m a -> m b -> m (Either a b) -- | Generates a list using a Range to determine the length. list :: MonadGen m => Range Int -> m a -> m [a] -- | Generates a seq using a Range to determine the length. seq :: MonadGen m => Range Int -> m a -> m (Seq a) -- | Generates a non-empty list using a Range to determine the -- length. nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a) -- | Generates a set using a Range to determine the length. -- -- This may fail to generate anything if the element generator -- cannot produce a large enough number of unique items to satify -- the required set size. set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a) -- | Generates a map using a Range to determine the length. -- -- This may fail to generate anything if the keys produced by the -- generator do not account for a large enough number of unique -- items to satify the required map size. map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v) -- | Freeze the size and seed used by a generator, so we can inspect the -- value which it will produce. -- -- This is used for implementing list and subtermMVec. It -- allows us to shrink the list itself before trying to shrink the values -- inside the list. freeze :: MonadGen m => m a -> m (a, m a) -- | Constructs a generator from a sub-term generator. -- -- Shrinks to the sub-term if possible. subterm :: MonadGen m => m a -> (a -> a) -> m a -- | Constructs a generator from a sub-term generator. -- -- Shrinks to the sub-term if possible. subtermM :: MonadGen m => m a -> (a -> m a) -> m a -- | Constructs a generator from two sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a -- | Constructs a generator from two sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a -- | Constructs a generator from three sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a -- | Constructs a generator from three sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a -- | Generates a random subsequence of a list. -- -- For example: -- --
-- Gen.print (Gen.subsequence [1..5]) ---- --
-- === Outcome === -- [1,2,4] -- === Shrinks === -- [] -- [2,4] -- [1,4] -- [1,2] --subsequence :: MonadGen m => [a] -> m [a] -- | Generates a random subset of a set. -- -- This shrinks towards the empty set. subset :: MonadGen m => Set a -> m (Set a) -- | Generates a random permutation of a list. -- -- This shrinks towards the order of the list being identical to the -- input list. shuffle :: MonadGen m => [a] -> m [a] -- | Generates a random permutation of a sequence. -- -- This shrinks towards the order of the sequence being identical to -- the input sequence. shuffleSeq :: MonadGen m => Seq a -> m (Seq a) -- | Generate a sample from a generator. -- -- This function is useful for examining a Gen in GHCi or other -- contexts. It is not appropriate for use in a test suite directly. You -- will only get a single sample from this function, and it will not give -- you a property test. The seed is random, so the test is not -- deterministic. -- -- If you only want a single test to run, then use withTests -- 1: -- --
-- prop_OnlyRunOnce :: Property -- prop_OnlyRunOnce = -- withTests 1 $ property $ do -- i <- Gen.int -- i /== 0 --sample :: (HasCallStack, MonadIO m) => Gen a -> m a -- | Run a generator with a random seed and print the outcome, and the -- first level of shrinks. -- --
-- Gen.print (Gen.enum 'a' 'f') ---- --
-- === Outcome === -- 'd' -- === Shrinks === -- 'a' -- 'b' -- 'c' --print :: (MonadIO m, Show a) => Gen a -> m () -- | Run a generator with a random seed and print the resulting shrink -- tree. -- --
-- Gen.printTree (Gen.enum 'a' 'f') ---- --
-- 'd' -- ├╼'a' -- ├╼'b' -- │ └╼'a' -- └╼'c' -- ├╼'a' -- └╼'b' -- └╼'a' ---- -- This may not terminate when the tree is very large. printTree :: (MonadIO m, Show a) => Gen a -> m () -- | Print the value produced by a generator, and the first level of -- shrinks, for the given size and seed. -- -- Use print to generate a value from a random seed. printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () -- | Print the shrink tree produced by a generator, for the given size and -- seed. -- -- Use printTree to generate a value from a random seed. printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () -- | Render the shrink tree produced by a generator, for the given size and -- seed. renderTree :: Show a => Size -> Seed -> Gen a -> String -- | Runs a generator, producing its shrink tree. runGenT :: forall (m :: Type -> Type) a. Size -> Seed -> GenT m a -> TreeT (MaybeT m) a -- | Run a generator, producing its shrink tree. -- -- Nothing means discarded, Just means we have a value. evalGen :: Size -> Seed -> Gen a -> Maybe (Tree a) -- | Runs a generator, producing its shrink tree. evalGenT :: forall (m :: Type -> Type) a. Monad m => Size -> Seed -> GenT m a -> TreeT m (Maybe a) -- | Map over a generator's shrink tree. mapGenT :: forall (m :: Type -> Type) a (n :: Type -> Type) b. (TreeT (MaybeT m) a -> TreeT (MaybeT n) b) -> GenT m a -> GenT n b -- | Generate a value with no shrinks from a Size and a Seed. generate :: MonadGen m => (Size -> Seed -> a) -> m a -- | Observe a generator's shrink tree. toTree :: (MonadGen m, GenBase m ~ Identity) => m a -> m (Tree a) -- | Lift a predefined shrink tree in to a generator, ignoring the seed and -- the size. toTreeMaybeT :: MonadGen m => m a -> m (TreeT (MaybeT (GenBase m)) a) -- | Lift a predefined shrink tree in to a generator, ignoring the seed and -- the size. fromTree :: MonadGen m => Tree a -> m a -- | Lift a predefined shrink tree in to a generator, ignoring the seed and -- the size. fromTreeT :: MonadGen m => TreeT (GenBase m) a -> m a -- | Lift a predefined shrink tree in to a generator, ignoring the seed and -- the size. fromTreeMaybeT :: MonadGen m => TreeT (MaybeT (GenBase m)) a -> m a -- | Lazily run the discard effects through the tree and reify it a -- Maybe (Tree a). -- -- Nothing means discarded, Just means we have a value. -- -- Discards in the child nodes of the tree are simply removed. runDiscardEffect :: TreeT (MaybeT Identity) a -> Maybe (Tree a) -- | Run the discard effects through the tree and reify them as -- Maybe values at the nodes. -- -- Nothing means discarded, Just means we have a value. runDiscardEffectT :: forall (m :: Type -> Type) a. Monad m => TreeT (MaybeT m) a -> TreeT m (Maybe a) -- | Scale a size using the golden ratio. -- --
-- golden x = x / φ -- golden x = x / 1.61803.. --golden :: Size -> Size -- | Check that list contains at least a certain number of elements. atLeast :: Int -> [a] -> Bool -- | Check if a character is in the surrogate category. isSurrogate :: Char -> Bool -- | Check if a character is one of the noncharacters '65534', '65535'. isNoncharacter :: Char -> Bool data Vec (n :: Nat) a [Nil] :: forall a. Vec 'Z a [:.] :: forall a (n1 :: Nat). a -> Vec n1 a -> Vec ('S n1) a infixr 5 :. data Nat Z :: Nat S :: Nat -> Nat -- | Constructs a generator from a number of sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subtermMVec :: forall m (n :: Nat) a. MonadGen m => Vec n (m a) -> (Vec n a -> m a) -> m a instance GHC.Base.Monad m => GHC.Base.Alternative (Hedgehog.Internal.Gen.GenT m) instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Gen.GenT m) instance Data.Foldable.Foldable (Hedgehog.Internal.Gen.Subterms n) instance Data.Foldable.Foldable (Hedgehog.Internal.Gen.Vec n) instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Gen.GenT m) instance GHC.Base.Functor (Hedgehog.Internal.Gen.Subterms n) instance GHC.Base.Functor (Hedgehog.Internal.Gen.Vec n) instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Gen.GenT instance Control.Monad.Morph.MMonad Hedgehog.Internal.Gen.GenT instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Gen.GenT m) instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (Hedgehog.Internal.Gen.GenT m) instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Gen.GenT m) instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Except.ExceptT x m) instance GHC.Base.Monad m => Hedgehog.Internal.Gen.MonadGen (Hedgehog.Internal.Gen.GenT m) instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Identity.IdentityT m) instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Maybe.MaybeT m) instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Reader.ReaderT r m) instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.State.Strict.StateT r m) instance Hedgehog.Internal.Gen.MonadGen m => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.State.Lazy.StateT r m) instance (Hedgehog.Internal.Gen.MonadGen m, GHC.Base.Monoid w) => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (Hedgehog.Internal.Gen.MonadGen m, GHC.Base.Monoid w) => Hedgehog.Internal.Gen.MonadGen (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Gen.GenT m) instance GHC.Base.Monad m => GHC.Base.MonadPlus (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Gen.GenT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Gen.GenT m) instance Hedgehog.Internal.Distributive.MonadTransDistributive Hedgehog.Internal.Gen.GenT instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Gen.GenT instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (Hedgehog.Internal.Gen.GenT m) instance (GHC.Base.Monad m, GHC.Base.Monoid a) => GHC.Base.Monoid (Hedgehog.Internal.Gen.GenT m a) instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Gen.GenT m) instance (GHC.Base.Monad m, GHC.Base.Semigroup a) => GHC.Base.Semigroup (Hedgehog.Internal.Gen.GenT m a) instance Data.Traversable.Traversable (Hedgehog.Internal.Gen.Subterms n) instance Data.Traversable.Traversable (Hedgehog.Internal.Gen.Vec n) module Hedgehog.Internal.Property -- | A property test, along with some configurable limits like how many -- times to run the test. data Property Property :: !PropertyConfig -> PropertyT IO () -> Property [propertyConfig] :: Property -> !PropertyConfig [propertyTest] :: Property -> PropertyT IO () -- | The property monad transformer allows both the generation of test -- inputs and the assertion of expectations. newtype PropertyT (m :: Type -> Type) a PropertyT :: TestT (GenT m) a -> PropertyT (m :: Type -> Type) a [unPropertyT] :: PropertyT (m :: Type -> Type) a -> TestT (GenT m) a -- | The name of a property. -- -- Should be constructed using OverloadedStrings: -- --
-- "apples" :: PropertyName --newtype PropertyName PropertyName :: String -> PropertyName [unPropertyName] :: PropertyName -> String -- | Configuration for a property test. data PropertyConfig PropertyConfig :: !DiscardLimit -> !ShrinkLimit -> !ShrinkRetries -> !TerminationCriteria -> Maybe Skip -> PropertyConfig [propertyDiscardLimit] :: PropertyConfig -> !DiscardLimit [propertyShrinkLimit] :: PropertyConfig -> !ShrinkLimit [propertyShrinkRetries] :: PropertyConfig -> !ShrinkRetries [propertyTerminationCriteria] :: PropertyConfig -> !TerminationCriteria -- | If this is Nothing, we take the Skip from the environment -- variable HEDGEHOG_SKIP. [propertySkip] :: PropertyConfig -> Maybe Skip -- | The number of successful tests that need to be run before a property -- test is considered successful. -- -- Can be constructed using numeric literals: -- --
-- 200 :: TestLimit --newtype TestLimit TestLimit :: Int -> TestLimit -- | The number of tests a property ran successfully. newtype TestCount TestCount :: Int -> TestCount -- | The number of discards to allow before giving up. -- -- Can be constructed using numeric literals: -- --
-- 10000 :: DiscardLimit --newtype DiscardLimit DiscardLimit :: Int -> DiscardLimit -- | The number of tests a property had to discard. newtype DiscardCount DiscardCount :: Int -> DiscardCount -- | The number of shrinks to try before giving up on shrinking. -- -- Can be constructed using numeric literals: -- --
-- 1000 :: ShrinkLimit --newtype ShrinkLimit ShrinkLimit :: Int -> ShrinkLimit -- | The numbers of times a property was able to shrink after a failing -- test. newtype ShrinkCount ShrinkCount :: Int -> ShrinkCount -- | Where to start running a property's tests. data Skip -- | Don't skip anything. SkipNothing :: Skip -- | Skip to a specific test number. If it fails, shrink as normal. If it -- passes, move on to the next test. Coverage checks are disabled. -- -- We also need to count discards, since failing "after 7 tests" points -- at a different generated value than failing "after 7 tests and 5 -- discards". SkipToTest :: TestCount -> DiscardCount -> Skip -- | Skip to a specific test number and shrink state. If it fails, stop -- without shrinking further. If it passes, the property will pass -- without running any more tests. -- -- Due to implementation details, all intermediate shrink states - those -- on the direct path from the original test input to the target state - -- will be tested too, and their results discarded. SkipToShrink :: TestCount -> DiscardCount -> ShrinkPath -> Skip -- | The path taken to reach a shrink state. newtype ShrinkPath ShrinkPath :: [Int] -> ShrinkPath -- | The number of times to re-run a test during shrinking. This is useful -- if you are testing something which fails non-deterministically and you -- want to increase the change of getting a good shrink. -- -- If you are doing parallel state machine testing, you should probably -- set shrink retries to something like 10. This will mean that -- during shrinking, a parallel test case requires 10 successful runs -- before it is passes and we try a different shrink. -- -- Can be constructed using numeric literals: -- --
-- 0 :: ShrinkRetries --newtype ShrinkRetries ShrinkRetries :: Int -> ShrinkRetries -- | Set the number of times a property should be executed before it is -- considered successful. -- -- If you have a test that does not involve any generators and thus does -- not need to run repeatedly, you can use withTests 1 to define -- a property that will only be checked once. withTests :: TestLimit -> Property -> Property -- | Set the number of times a property is allowed to discard before the -- test runner gives up. withDiscards :: DiscardLimit -> Property -> Property -- | Set the number of times a property is allowed to shrink before the -- test runner gives up and prints the counterexample. withShrinks :: ShrinkLimit -> Property -> Property -- | Set the number of times a property will be executed for each shrink -- before the test runner gives up and tries a different shrink. See -- ShrinkRetries for more information. withRetries :: ShrinkRetries -> Property -> Property -- | Set the target that a property will skip to before it starts to run. withSkip :: Skip -> Property -> Property -- | Creates a property with the default configuration. property :: HasCallStack => PropertyT IO () -> Property -- | Lift a test in to a property. -- -- Because both TestT and PropertyT have MonadTest -- instances, this function is not often required. It can however be -- useful for writing functions directly in TestT and thus gaining -- a MonadTransControl instance at the expense of not being able -- to generate additional inputs using forAll. -- -- An example where this is useful is parallel state machine testing, as -- executeParallel requires MonadBaseControl IO in -- order to be able to spawn threads in MonadTest. test :: forall (m :: Type -> Type) a. Monad m => TestT m a -> PropertyT m a -- | Generates a random input for the test by running the provided -- generator. forAll :: forall (m :: Type -> Type) a. (Monad m, Show a, HasCallStack) => Gen a -> PropertyT m a -- | Generates a random input for the test by running the provided -- generator. forAllT :: forall (m :: Type -> Type) a. (Monad m, Show a, HasCallStack) => GenT m a -> PropertyT m a -- | Generates a random input for the test by running the provided -- generator. -- -- This is a the same as forAll but allows the user to provide -- a custom rendering function. This is useful for values which -- don't have a Show instance. forAllWith :: forall (m :: Type -> Type) a. (Monad m, HasCallStack) => (a -> String) -> Gen a -> PropertyT m a -- | Generates a random input for the test by running the provided -- generator. -- -- This is a the same as forAllT but allows the user to provide -- a custom rendering function. This is useful for values which -- don't have a Show instance. forAllWithT :: forall (m :: Type -> Type) a. (Monad m, HasCallStack) => (a -> String) -> GenT m a -> PropertyT m a -- | The minimum amount of tests to run for a Property defaultMinTests :: TestLimit -- | Discards the current test entirely. discard :: forall (m :: Type -> Type) a. Monad m => PropertyT m a -- | Compress a Skip into a hopefully-short alphanumeric string. -- -- The bit that might be long is the ShrinkPath in -- SkipToShrink. For that, we encode the path components in base -- 26, alternating between uppercase and lowercase alphabets to -- distinguish list elements. Additionally when we have runs of equal -- components, we use the normal base 10 encoding to indicate the length. -- -- This gives something which is hopefully quite short, but a human can -- roughly interpret it by eyeball. skipCompress :: Skip -> String -- | Compress a ShrinkPath into a hopefully-short alphanumeric -- string. -- -- We encode the path components in base 26, alternating between -- uppercase and lowercase alphabets to distinguish list elements. -- Additionally when we have runs of equal components, we use the normal -- base 10 encoding to indicate the length. shrinkPathCompress :: ShrinkPath -> String -- | Decompress a Skip. -- -- This satisfies -- --
-- skipDecompress (skipCompress a) == Just a --skipDecompress :: String -> Maybe Skip -- | Decompress a ShrinkPath. -- -- This satisfies -- --
-- shrinkPathDecompress (shrinkPathCompress a) == Just a --shrinkPathDecompress :: String -> Maybe ShrinkPath -- | A named collection of property tests. data Group Group :: !GroupName -> ![(PropertyName, Property)] -> Group [groupName] :: Group -> !GroupName [groupProperties] :: Group -> ![(PropertyName, Property)] -- | The name of a group of properties. -- -- Should be constructed using OverloadedStrings: -- --
-- "fruit" :: GroupName --newtype GroupName GroupName :: String -> GroupName [unGroupName] :: GroupName -> String -- | The number of properties in a group. newtype PropertyCount PropertyCount :: Int -> PropertyCount class Monad m => MonadTest (m :: Type -> Type) liftTest :: MonadTest m => Test a -> m a -- | A test monad allows the assertion of expectations. type Test = TestT Identity -- | A test monad transformer allows the assertion of expectations. newtype TestT (m :: Type -> Type) a TestT :: ExceptT Failure (WriterT Journal m) a -> TestT (m :: Type -> Type) a [unTest] :: TestT (m :: Type -> Type) a -> ExceptT Failure (WriterT Journal m) a -- | Log messages which are recorded during a test run. data Log Annotation :: Maybe Span -> String -> Log Footnote :: String -> Log Label :: Label Cover -> Log -- | A record containing the details of a test run. newtype Journal Journal :: [Log] -> Journal [journalLogs] :: Journal -> [Log] -- | Details on where and why a test failed. data Failure Failure :: Maybe Span -> String -> Maybe Diff -> Failure -- | The difference between some expected and actual value. data Diff Diff :: String -> String -> String -> String -> String -> ValueDiff -> Diff [diffPrefix] :: Diff -> String [diffRemoved] :: Diff -> String [diffInfix] :: Diff -> String [diffAdded] :: Diff -> String [diffSuffix] :: Diff -> String [diffValue] :: Diff -> ValueDiff -- | Annotates the source code with a message that might be useful for -- debugging a test failure. annotate :: (MonadTest m, HasCallStack) => String -> m () -- | Annotates the source code with a value that might be useful for -- debugging a test failure. annotateShow :: (MonadTest m, Show a, HasCallStack) => a -> m () -- | Logs a message to be displayed as additional information in the footer -- of the failure report. footnote :: MonadTest m => String -> m () -- | Logs a value to be displayed as additional information in the footer -- of the failure report. footnoteShow :: (MonadTest m, Show a) => a -> m () -- | Causes a test to fail. failure :: (MonadTest m, HasCallStack) => m a -- | Another name for pure (). success :: MonadTest m => m () -- | Fails the test if the condition provided is False. assert :: (MonadTest m, HasCallStack) => Bool -> m () -- | Fails the test and shows a git-like diff if the comparison operation -- evaluates to False when applied to its arguments. -- -- The comparison function is the second argument, which may be -- counter-intuitive to Haskell programmers. However, it allows operators -- to be written infix for easy reading: -- --
-- diff y (<) 87 -- diff x (<=) r ---- -- This function behaves like the unix diff tool, which gives a -- 0 exit code if the compared files are identical, or a 1 exit code code -- otherwise. Like unix diff, if the arguments fail the -- comparison, a /diff is shown. diff :: (MonadTest m, Show a, Show b, HasCallStack) => a -> (a -> b -> Bool) -> b -> m () -- | Fails the test if the two arguments provided are not equal. (===) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m () infix 4 === -- | Fails the test if the two arguments provided are equal. (/==) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m () infix 4 /== -- | Fails the test if the value throws an exception when evaluated to weak -- head normal form (WHNF). eval :: (MonadTest m, HasCallStack) => a -> m a -- | Fails the test if the value throws an exception when evaluated to -- normal form (NF). evalNF :: (MonadTest m, NFData a, HasCallStack) => a -> m a -- | Fails the test if the action throws an exception. -- -- The benefit of using this over simply letting the exception bubble -- up is that the location of the closest evalM will be -- shown in the output. evalM :: (MonadTest m, MonadCatch m, HasCallStack) => m a -> m a -- | Fails the test if the IO action throws an exception. -- -- The benefit of using this over liftIO is that the location -- of the exception will be shown in the output. evalIO :: (MonadTest m, MonadIO m, HasCallStack) => IO a -> m a -- | Fails the test if the Either is Left, otherwise returns -- the value in the Right. evalEither :: (MonadTest m, Show x, HasCallStack) => Either x a -> m a -- | Fails the test if the action throws an exception, or if the -- Either is Left, otherwise returns the value in the -- Right. evalEitherM :: (MonadTest m, Show x, MonadCatch m, HasCallStack) => m (Either x a) -> m a -- | Fails the test if the ExceptT is Left, otherwise returns -- the value in the Right. evalExceptT :: (MonadTest m, Show x, HasCallStack) => ExceptT x m a -> m a -- | Fails the test if the Maybe is Nothing, otherwise -- returns the value in the Just. evalMaybe :: (MonadTest m, HasCallStack) => Maybe a -> m a -- | Fails the test if the action throws an exception, or if the -- Maybe is Nothing, otherwise returns the value in the -- Just. evalMaybeM :: (MonadTest m, MonadCatch m, HasCallStack) => m (Maybe a) -> m a -- | The extent to which all classifiers cover a test. -- -- When a given classification's coverage does not exceed the -- required minimum, the test will be failed. newtype Coverage a Coverage :: Map LabelName (Label a) -> Coverage a [coverageLabels] :: Coverage a -> Map LabelName (Label a) -- | The extent to which a test is covered by a classifier. -- -- When a classifier's coverage does not exceed the required minimum, -- the test will be failed. data Label a MkLabel :: !LabelName -> !Maybe Span -> !CoverPercentage -> !a -> Label a [labelName] :: Label a -> !LabelName [labelLocation] :: Label a -> !Maybe Span [labelMinimum] :: Label a -> !CoverPercentage [labelAnnotation] :: Label a -> !a -- | The name of a classifier. -- -- Should be constructed using OverloadedStrings: -- --
-- "apples" :: LabelName --newtype LabelName LabelName :: String -> LabelName [unLabelName] :: LabelName -> String -- | Require a certain percentage of the tests to be covered by the -- classifier. -- --
-- prop_with_coverage :: Property -- prop_with_coverage = -- property $ do -- match <- forAll Gen.bool -- cover 30 "True" $ match -- cover 30 "False" $ not match ---- -- The example above requires a minimum of 30% coverage for both -- classifiers. If these requirements are not met, it will fail the test. cover :: (MonadTest m, HasCallStack) => CoverPercentage -> LabelName -> Bool -> m () -- | Records the proportion of tests which satisfy a given condition. -- --
-- prop_with_classifier :: Property -- prop_with_classifier = -- property $ do -- xs <- forAll $ Gen.list (Range.linear 0 100) Gen.alpha -- for_ xs $ \x -> do -- classify "newborns" $ x == 0 -- classify "children" $ x > 0 && x < 13 -- classify "teens" $ x > 12 && x < 20 --classify :: (MonadTest m, HasCallStack) => LabelName -> Bool -> m () -- | Add a label for each test run. It produces a table showing the -- percentage of test runs that produced each label. label :: (MonadTest m, HasCallStack) => LabelName -> m () -- | Like label, but uses Show to render its argument for -- display. collect :: (MonadTest m, Show a, HasCallStack) => a -> m () coverPercentage :: TestCount -> CoverCount -> CoverPercentage labelCovered :: TestCount -> Label CoverCount -> Bool -- | All labels are covered coverageSuccess :: TestCount -> Coverage CoverCount -> Bool coverageFailures :: TestCount -> Coverage CoverCount -> [Label CoverCount] journalCoverage :: Journal -> Coverage CoverCount -- | Whether a test is covered by a classifier, and therefore belongs to a -- Class. data Cover NoCover :: Cover Cover :: Cover -- | The total number of tests which are covered by a classifier. -- -- Can be constructed using numeric literals: -- --
-- 30 :: CoverCount --newtype CoverCount CoverCount :: Int -> CoverCount [unCoverCount] :: CoverCount -> Int -- | The relative number of tests which are covered by a classifier. -- -- Can be constructed using numeric literals: -- --
-- 30 :: CoverPercentage --newtype CoverPercentage CoverPercentage :: Double -> CoverPercentage [unCoverPercentage] :: CoverPercentage -> Double toCoverCount :: Cover -> CoverCount -- | The acceptable occurrence of false positives -- -- Example, Confidence 10^9 would mean that you'd accept a false -- positive for 1 in 10^9 tests. newtype Confidence Confidence :: Int64 -> Confidence [unConfidence] :: Confidence -> Int64 data TerminationCriteria EarlyTermination :: Confidence -> TestLimit -> TerminationCriteria NoEarlyTermination :: Confidence -> TestLimit -> TerminationCriteria NoConfidenceTermination :: TestLimit -> TerminationCriteria -- | Is true when the test coverage satisfies the specified -- Confidence contstraint for all 'Coverage CoverCount's confidenceSuccess :: TestCount -> Confidence -> Coverage CoverCount -> Bool -- | Is true when there exists a label that is sure to have failed -- according to the Confidence constraint confidenceFailure :: TestCount -> Confidence -> Coverage CoverCount -> Bool -- | Make sure that the result is statistically significant in accordance -- to the passed Confidence withConfidence :: Confidence -> Property -> Property verifiedTermination :: Property -> Property -- | The default confidence allows one false positive in 10^9 tests defaultConfidence :: Confidence -- | The default configuration for a property test. defaultConfig :: PropertyConfig -- | Map a config modification function over a property. mapConfig :: (PropertyConfig -> PropertyConfig) -> Property -> Property -- | Fails with an error that shows the difference between two values. failDiff :: (MonadTest m, Show a, Show b, HasCallStack) => a -> b -> m () -- | Fails with an error which renders the type of an exception and its -- error message. failException :: (MonadTest m, HasCallStack) => SomeException -> m a -- | Fail the test with an error message, useful for building other failure -- combinators. failWith :: (MonadTest m, HasCallStack) => Maybe Diff -> String -> m a -- | Log some information which might be relevant to a potential test -- failure. writeLog :: MonadTest m => Log -> m () mkTest :: (Either Failure a, Journal) -> Test a mkTestT :: m (Either Failure a, Journal) -> TestT m a runTest :: Test a -> (Either Failure a, Journal) runTestT :: TestT m a -> m (Either Failure a, Journal) wilsonBounds :: Integer -> Integer -> Double -> (Double, Double) instance GHC.Base.MonadPlus m => GHC.Base.Alternative (Hedgehog.Internal.Property.PropertyT m) instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Property.PropertyT m) instance GHC.Base.Monad m => GHC.Base.Applicative (Hedgehog.Internal.Property.TestT m) instance GHC.Enum.Enum Hedgehog.Internal.Property.DiscardCount instance GHC.Enum.Enum Hedgehog.Internal.Property.DiscardLimit instance GHC.Enum.Enum Hedgehog.Internal.Property.PropertyCount instance GHC.Enum.Enum Hedgehog.Internal.Property.ShrinkCount instance GHC.Enum.Enum Hedgehog.Internal.Property.ShrinkLimit instance GHC.Enum.Enum Hedgehog.Internal.Property.ShrinkRetries instance GHC.Enum.Enum Hedgehog.Internal.Property.TestCount instance GHC.Enum.Enum Hedgehog.Internal.Property.TestLimit instance GHC.Classes.Eq Hedgehog.Internal.Property.Confidence instance GHC.Classes.Eq Hedgehog.Internal.Property.Cover instance GHC.Classes.Eq Hedgehog.Internal.Property.CoverCount instance GHC.Classes.Eq Hedgehog.Internal.Property.CoverPercentage instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Property.Coverage a) instance GHC.Classes.Eq Hedgehog.Internal.Property.Diff instance GHC.Classes.Eq Hedgehog.Internal.Property.DiscardCount instance GHC.Classes.Eq Hedgehog.Internal.Property.DiscardLimit instance GHC.Classes.Eq Hedgehog.Internal.Property.Failure instance GHC.Classes.Eq Hedgehog.Internal.Property.GroupName instance GHC.Classes.Eq Hedgehog.Internal.Property.Journal instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Property.Label a) instance GHC.Classes.Eq Hedgehog.Internal.Property.LabelName instance GHC.Classes.Eq Hedgehog.Internal.Property.Log instance GHC.Classes.Eq Hedgehog.Internal.Property.PropertyConfig instance GHC.Classes.Eq Hedgehog.Internal.Property.PropertyCount instance GHC.Classes.Eq Hedgehog.Internal.Property.PropertyName instance GHC.Classes.Eq Hedgehog.Internal.Property.ShrinkCount instance GHC.Classes.Eq Hedgehog.Internal.Property.ShrinkLimit instance GHC.Classes.Eq Hedgehog.Internal.Property.ShrinkPath instance GHC.Classes.Eq Hedgehog.Internal.Property.ShrinkRetries instance GHC.Classes.Eq Hedgehog.Internal.Property.Skip instance GHC.Classes.Eq Hedgehog.Internal.Property.TerminationCriteria instance GHC.Classes.Eq Hedgehog.Internal.Property.TestCount instance GHC.Classes.Eq Hedgehog.Internal.Property.TestLimit instance Data.Foldable.Foldable Hedgehog.Internal.Property.Coverage instance Data.Foldable.Foldable Hedgehog.Internal.Property.Label instance GHC.Real.Fractional Hedgehog.Internal.Property.CoverPercentage instance GHC.Base.Functor Hedgehog.Internal.Property.Coverage instance GHC.Base.Functor Hedgehog.Internal.Property.Label instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Property.PropertyT m) instance GHC.Base.Functor m => GHC.Base.Functor (Hedgehog.Internal.Property.TestT m) instance GHC.Real.Integral Hedgehog.Internal.Property.DiscardCount instance GHC.Real.Integral Hedgehog.Internal.Property.DiscardLimit instance GHC.Real.Integral Hedgehog.Internal.Property.PropertyCount instance GHC.Real.Integral Hedgehog.Internal.Property.ShrinkCount instance GHC.Real.Integral Hedgehog.Internal.Property.ShrinkLimit instance GHC.Real.Integral Hedgehog.Internal.Property.ShrinkRetries instance GHC.Real.Integral Hedgehog.Internal.Property.TestCount instance GHC.Real.Integral Hedgehog.Internal.Property.TestLimit instance Data.String.IsString Hedgehog.Internal.Property.GroupName instance Data.String.IsString Hedgehog.Internal.Property.LabelName instance Data.String.IsString Hedgehog.Internal.Property.PropertyName instance Data.String.IsString Hedgehog.Internal.Property.Skip instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.Confidence instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.DiscardCount instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.DiscardLimit instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.GroupName instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.PropertyConfig instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.PropertyName instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.ShrinkLimit instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.ShrinkPath instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.ShrinkRetries instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.Skip instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.TerminationCriteria instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.TestCount instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Property.TestLimit instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Property.PropertyT instance Control.Monad.Morph.MFunctor Hedgehog.Internal.Property.TestT instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Hedgehog.Internal.Property.TestT m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Hedgehog.Internal.Property.TestT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Hedgehog.Internal.Property.TestT m) instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (Hedgehog.Internal.Property.TestT m) instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (Hedgehog.Internal.Property.PropertyT m) instance GHC.Base.Monad m => Control.Monad.Fail.MonadFail (Hedgehog.Internal.Property.TestT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Hedgehog.Internal.Property.TestT m) instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Hedgehog.Internal.Property.TestT m) instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Trans.Resource.Internal.MonadResource m => Control.Monad.Trans.Resource.Internal.MonadResource (Hedgehog.Internal.Property.TestT m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Hedgehog.Internal.Property.TestT m) instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Property.PropertyT m) instance GHC.Base.Monad m => GHC.Base.Monad (Hedgehog.Internal.Property.TestT m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Cont.ContT r m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Except.ExceptT x m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Identity.IdentityT m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Maybe.MaybeT m) instance GHC.Base.Monad m => Hedgehog.Internal.Property.MonadTest (Hedgehog.Internal.Property.PropertyT m) instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.RWS.Strict.RWST r w s m) instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.RWS.Lazy.RWST r w s m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Reader.ReaderT r m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Resource.Internal.ResourceT m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.State.Strict.StateT s m) instance Hedgehog.Internal.Property.MonadTest m => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.State.Lazy.StateT s m) instance GHC.Base.Monad m => Hedgehog.Internal.Property.MonadTest (Hedgehog.Internal.Property.TestT m) instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (Hedgehog.Internal.Property.MonadTest m, GHC.Base.Monoid w) => Hedgehog.Internal.Property.MonadTest (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Hedgehog.Internal.Property.TestT m) instance Control.Monad.Trans.Control.MonadTransControl Hedgehog.Internal.Property.TestT instance Hedgehog.Internal.Distributive.MonadTransDistributive Hedgehog.Internal.Property.PropertyT instance Hedgehog.Internal.Distributive.MonadTransDistributive Hedgehog.Internal.Property.TestT instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Property.PropertyT instance Control.Monad.Trans.Class.MonadTrans Hedgehog.Internal.Property.TestT instance GHC.Base.Monoid Hedgehog.Internal.Property.Cover instance GHC.Base.Monoid Hedgehog.Internal.Property.CoverCount instance (GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Hedgehog.Internal.Property.Coverage a) instance GHC.Base.Monoid Hedgehog.Internal.Property.Journal instance GHC.Base.Monoid Hedgehog.Internal.Property.LabelName instance GHC.Num.Num Hedgehog.Internal.Property.Confidence instance GHC.Num.Num Hedgehog.Internal.Property.CoverCount instance GHC.Num.Num Hedgehog.Internal.Property.CoverPercentage instance GHC.Num.Num Hedgehog.Internal.Property.DiscardCount instance GHC.Num.Num Hedgehog.Internal.Property.DiscardLimit instance GHC.Num.Num Hedgehog.Internal.Property.PropertyCount instance GHC.Num.Num Hedgehog.Internal.Property.ShrinkCount instance GHC.Num.Num Hedgehog.Internal.Property.ShrinkLimit instance GHC.Num.Num Hedgehog.Internal.Property.ShrinkRetries instance GHC.Num.Num Hedgehog.Internal.Property.TestCount instance GHC.Num.Num Hedgehog.Internal.Property.TestLimit instance GHC.Classes.Ord Hedgehog.Internal.Property.Confidence instance GHC.Classes.Ord Hedgehog.Internal.Property.Cover instance GHC.Classes.Ord Hedgehog.Internal.Property.CoverCount instance GHC.Classes.Ord Hedgehog.Internal.Property.CoverPercentage instance GHC.Classes.Ord Hedgehog.Internal.Property.DiscardCount instance GHC.Classes.Ord Hedgehog.Internal.Property.DiscardLimit instance GHC.Classes.Ord Hedgehog.Internal.Property.GroupName instance GHC.Classes.Ord Hedgehog.Internal.Property.LabelName instance GHC.Classes.Ord Hedgehog.Internal.Property.PropertyConfig instance GHC.Classes.Ord Hedgehog.Internal.Property.PropertyCount instance GHC.Classes.Ord Hedgehog.Internal.Property.PropertyName instance GHC.Classes.Ord Hedgehog.Internal.Property.ShrinkCount instance GHC.Classes.Ord Hedgehog.Internal.Property.ShrinkLimit instance GHC.Classes.Ord Hedgehog.Internal.Property.ShrinkPath instance GHC.Classes.Ord Hedgehog.Internal.Property.ShrinkRetries instance GHC.Classes.Ord Hedgehog.Internal.Property.Skip instance GHC.Classes.Ord Hedgehog.Internal.Property.TerminationCriteria instance GHC.Classes.Ord Hedgehog.Internal.Property.TestCount instance GHC.Classes.Ord Hedgehog.Internal.Property.TestLimit instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Property.PropertyT m) instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Hedgehog.Internal.Property.TestT m) instance GHC.Real.Real Hedgehog.Internal.Property.DiscardCount instance GHC.Real.Real Hedgehog.Internal.Property.DiscardLimit instance GHC.Real.Real Hedgehog.Internal.Property.PropertyCount instance GHC.Real.Real Hedgehog.Internal.Property.ShrinkCount instance GHC.Real.Real Hedgehog.Internal.Property.ShrinkLimit instance GHC.Real.Real Hedgehog.Internal.Property.ShrinkRetries instance GHC.Real.Real Hedgehog.Internal.Property.TestCount instance GHC.Real.Real Hedgehog.Internal.Property.TestLimit instance GHC.Base.Semigroup Hedgehog.Internal.Property.Cover instance GHC.Base.Semigroup Hedgehog.Internal.Property.CoverCount instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Hedgehog.Internal.Property.Coverage a) instance GHC.Base.Semigroup Hedgehog.Internal.Property.GroupName instance GHC.Base.Semigroup Hedgehog.Internal.Property.Journal instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Hedgehog.Internal.Property.Label a) instance GHC.Base.Semigroup Hedgehog.Internal.Property.LabelName instance GHC.Base.Semigroup Hedgehog.Internal.Property.PropertyName instance GHC.Show.Show Hedgehog.Internal.Property.Confidence instance GHC.Show.Show Hedgehog.Internal.Property.Cover instance GHC.Show.Show Hedgehog.Internal.Property.CoverCount instance GHC.Show.Show Hedgehog.Internal.Property.CoverPercentage instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Property.Coverage a) instance GHC.Show.Show Hedgehog.Internal.Property.Diff instance GHC.Show.Show Hedgehog.Internal.Property.DiscardCount instance GHC.Show.Show Hedgehog.Internal.Property.DiscardLimit instance GHC.Show.Show Hedgehog.Internal.Property.Failure instance GHC.Show.Show Hedgehog.Internal.Property.GroupName instance GHC.Show.Show Hedgehog.Internal.Property.Journal instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Property.Label a) instance GHC.Show.Show Hedgehog.Internal.Property.LabelName instance GHC.Show.Show Hedgehog.Internal.Property.Log instance GHC.Show.Show Hedgehog.Internal.Property.PropertyConfig instance GHC.Show.Show Hedgehog.Internal.Property.PropertyCount instance GHC.Show.Show Hedgehog.Internal.Property.PropertyName instance GHC.Show.Show Hedgehog.Internal.Property.ShrinkCount instance GHC.Show.Show Hedgehog.Internal.Property.ShrinkLimit instance GHC.Show.Show Hedgehog.Internal.Property.ShrinkPath instance GHC.Show.Show Hedgehog.Internal.Property.ShrinkRetries instance GHC.Show.Show Hedgehog.Internal.Property.Skip instance GHC.Show.Show Hedgehog.Internal.Property.TerminationCriteria instance GHC.Show.Show Hedgehog.Internal.Property.TestCount instance GHC.Show.Show Hedgehog.Internal.Property.TestLimit instance Data.Traversable.Traversable Hedgehog.Internal.Property.Coverage instance Data.Traversable.Traversable Hedgehog.Internal.Property.Label module Hedgehog.Internal.Tripping -- | Test that a pair of encode / decode functions are compatible. -- -- Given a printer from some type a -> b, and a parser with a -- potential failure case b -> f a. Ensure that a valid -- a round trips through the "print" and "parse" to yield the -- same a. -- -- For example, types should have tripping Read and -- Show instances: -- --
-- trippingShowRead :: (Show a, Read a, Eq a, MonadTest m) => a -> m () -- trippingShowRead a = tripping a show readEither --tripping :: (MonadTest m, Applicative f, Show b, Show (f a), Eq (f a), HasCallStack) => a -> (a -> b) -> (b -> f a) -> m () module Hedgehog.Internal.State -- | Variables are the potential or actual result of executing an action. -- They are parameterised by either Symbolic or Concrete -- depending on the phase of the test. -- -- Symbolic variables are the potential results of actions. These -- are used when generating the sequence of actions to execute. They -- allow actions which occur later in the sequence to make use of the -- result of an action which came earlier in the sequence. -- -- Concrete variables are the actual results of actions. These are -- used during test execution. They provide access to the actual runtime -- value of a variable. -- -- The state update Callback for a command needs to be polymorphic -- in the type of variable because it is used in both the generation and -- the execution phase. -- -- The order of arguments makes Var FunctorB and -- TraversableB, which is how Symbolic values are turned -- into Concrete ones. newtype Var a (v :: Type -> Type) Var :: v a -> Var a (v :: Type -> Type) -- | Take the value from a concrete variable. concrete :: Var a Concrete -> a -- | Take the value from an opaque concrete variable. opaque :: Var (Opaque a) Concrete -> a -- | Concrete values: At test-execution time, Symbolic values from -- generation are replaced with Concrete values from performing -- actions. This type gives us something of the same kind as -- Symbolic to pass as a type argument to Var. newtype Concrete a [Concrete] :: forall a. a -> Concrete a -- | Symbolic values: Because hedgehog generates actions in a separate -- phase before execution, you will sometimes need to refer to the result -- of a previous action in a generator without knowing the value of the -- result (e.g., to get the ID of a previously-created user). -- -- Symbolic variables provide a token to stand in for the actual -- variables at generation time (and in Require/Update -- callbacks). At execution time, real values are available, so your -- execute actions work on Concrete variables. -- -- See also: Command, Var data Symbolic a [Symbolic] :: forall a. Typeable a => Name -> Symbolic a -- | Symbolic variable names. newtype Name Name :: Int -> Name -- | A mapping of symbolic values to concrete values. newtype Environment Environment :: Map Name Dynamic -> Environment [unEnvironment] :: Environment -> Map Name Dynamic -- | Environment errors. data EnvironmentError EnvironmentValueNotFound :: !Name -> EnvironmentError EnvironmentTypeError :: !TypeRep -> !TypeRep -> EnvironmentError -- | Create an empty environment. emptyEnvironment :: Environment -- | Insert a symbolic / concrete pairing in to the environment. insertConcrete :: Symbolic a -> Concrete a -> Environment -> Environment -- | Cast a Dynamic in to a concrete value. reifyDynamic :: Typeable a => Dynamic -> Either EnvironmentError (Concrete a) -- | Turns an environment in to a function for looking up a concrete value -- from a symbolic one. reifyEnvironment :: Environment -> forall a. () => Symbolic a -> Either EnvironmentError (Concrete a) -- | Convert a symbolic structure to a concrete one, using the provided -- environment. reify :: TraversableB t => Environment -> t Symbolic -> Either EnvironmentError (t Concrete) -- | The specification for the expected behaviour of an Action. -- These are used to generate sequences of actions to test. -- -- This is the main type you will use when writing state machine tests. -- gen is usually an instance of MonadGen, and m -- is usually an instance of MonadTest. These constraints appear -- when you pass your Command list to sequential or -- parallel. data Command (gen :: Type -> Type) (m :: Type -> Type) (state :: Type -> Type -> Type) Command :: (state Symbolic -> Maybe (gen (input Symbolic))) -> (input Concrete -> m output) -> [Callback input output state] -> Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -- | A generator which provides random arguments for a command. If the -- command cannot be executed in the current state, it should return -- Nothing. [commandGen] :: Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> state Symbolic -> Maybe (gen (input Symbolic)) -- | Executes a command using the arguments generated by commandGen. [commandExecute] :: Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> input Concrete -> m output -- | A set of callbacks which provide optional command configuration such -- as pre-condtions, post-conditions and state updates. [commandCallbacks] :: Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Callback input output state] -- | Optional command configuration. data Callback (input :: Type -> Type -> Type) output (state :: Type -> Type -> Type) -- | A pre-condition for a command that must be verified before the command -- can be executed. This is mainly used during shrinking to ensure that -- it is still OK to run a command despite the fact that some previously -- executed commands may have been removed from the sequence. Require :: (state Symbolic -> input Symbolic -> Bool) -> Callback (input :: (Type -> Type) -> Type) output (state :: (Type -> Type) -> Type) -- | Updates the model state, given the input and output of the command. -- Note that this function is polymorphic in the type of values. This is -- because it must work over Symbolic values when we are -- generating actions, and Concrete values when we are executing -- them. Update :: (forall (v :: Type -> Type). Ord1 v => state v -> input v -> Var output v -> state v) -> Callback (input :: (Type -> Type) -> Type) output (state :: (Type -> Type) -> Type) -- | A post-condition for a command that must be verified for the command -- to be considered a success. -- -- This callback receives the state prior to execution as the first -- argument, and the state after execution as the second argument. Ensure :: (state Concrete -> state Concrete -> input Concrete -> output -> Test ()) -> Callback (input :: (Type -> Type) -> Type) output (state :: (Type -> Type) -> Type) -- | An instantiation of a Command which can be executed, and its -- effect evaluated. data Action (m :: Type -> Type) (state :: Type -> Type -> Type) Action :: input Symbolic -> Symbolic output -> (input Concrete -> m output) -> (state Symbolic -> input Symbolic -> Bool) -> (forall (v :: Type -> Type). Ord1 v => state v -> input v -> Var output v -> state v) -> (state Concrete -> state Concrete -> input Concrete -> output -> Test ()) -> Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) [actionInput] :: Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> input Symbolic [actionOutput] :: Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> Symbolic output [actionExecute] :: Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> input Concrete -> m output [actionRequire] :: Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> state Symbolic -> input Symbolic -> Bool [actionUpdate] :: Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> forall (v :: Type -> Type). Ord1 v => state v -> input v -> Var output v -> state v [actionEnsure] :: Action (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> state Concrete -> state Concrete -> input Concrete -> output -> Test () -- | A sequence of actions to execute. newtype Sequential (m :: Type -> Type) (state :: Type -> Type -> Type) Sequential :: [Action m state] -> Sequential (m :: Type -> Type) (state :: (Type -> Type) -> Type) -- | The sequence of actions. [sequentialActions] :: Sequential (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | A sequential prefix of actions to execute, with two branches to -- execute in parallel. data Parallel (m :: Type -> Type) (state :: Type -> Type -> Type) Parallel :: [Action m state] -> [Action m state] -> [Action m state] -> Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -- | The sequential prefix. [parallelPrefix] :: Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | The first branch. [parallelBranch1] :: Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | The second branch. [parallelBranch2] :: Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | Collects all the symbolic values in a data structure and produces a -- set of all the variables they refer to. takeVariables :: TraversableB t => t Symbolic -> Map Name TypeRep -- | Checks that the symbolic values in the data structure refer only to -- the variables in the provided set, and that they are of the correct -- type. variablesOK :: TraversableB t => t Symbolic -> Map Name TypeRep -> Bool -- | Drops invalid actions from the sequence. dropInvalid :: forall (m :: Type -> Type) (state :: (Type -> Type) -> Type). [Action m state] -> State (Context state) [Action m state] -- | Generates a single action from a set of possible commands. action :: forall (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type). (MonadGen gen, MonadTest m) => [Command gen m state] -> GenT (StateT (Context state) (GenBase gen)) (Action m state) -- | Generates a sequence of actions from an initial model state and set of -- commands. sequential :: forall gen (m :: Type -> Type) state. (MonadGen gen, MonadTest m) => Range Int -> (forall (v :: Type -> Type). () => state v) -> [Command gen m state] -> gen (Sequential m state) -- | Given the initial model state and set of commands, generates prefix -- actions to be run sequentially, followed by two branches to be run in -- parallel. parallel :: forall gen (m :: Type -> Type) state. (MonadGen gen, MonadTest m) => Range Int -> Range Int -> (forall (v :: Type -> Type). () => state v) -> [Command gen m state] -> gen (Parallel m state) -- | Executes a list of actions sequentially, verifying that all -- post-conditions are met and no exceptions are thrown. -- -- To generate a sequence of actions to execute, see the -- sequential combinator in the Hedgehog.Gen module. executeSequential :: (MonadTest m, MonadCatch m, HasCallStack) => (forall (v :: Type -> Type). () => state v) -> Sequential m state -> m () -- | Executes the prefix actions sequentially, then executes the two -- branches in parallel, verifying that no exceptions are thrown and that -- there is at least one sequential interleaving where all the -- post-conditions are met. -- -- To generate parallel actions to execute, see the parallel -- combinator in the Hedgehog.Gen module. executeParallel :: (MonadTest m, MonadCatch m, MonadBaseControl IO m, HasCallStack) => (forall (v :: Type -> Type). () => state v) -> Parallel m state -> m () instance Data.Functor.Classes.Eq1 Hedgehog.Internal.State.Concrete instance Data.Functor.Classes.Eq1 Hedgehog.Internal.State.Symbolic instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.State.Concrete a) instance GHC.Classes.Eq Hedgehog.Internal.State.EnvironmentError instance GHC.Classes.Eq Hedgehog.Internal.State.Name instance GHC.Classes.Eq (Hedgehog.Internal.State.Symbolic a) instance (GHC.Classes.Eq a, Data.Functor.Classes.Eq1 v) => GHC.Classes.Eq (Hedgehog.Internal.State.Var a v) instance Data.Foldable.Foldable Hedgehog.Internal.State.Concrete instance Barbies.Internal.FunctorB.FunctorB (Hedgehog.Internal.State.Var a) instance GHC.Base.Functor Hedgehog.Internal.State.Concrete instance GHC.Num.Num Hedgehog.Internal.State.Name instance Data.Functor.Classes.Ord1 Hedgehog.Internal.State.Concrete instance Data.Functor.Classes.Ord1 Hedgehog.Internal.State.Symbolic instance GHC.Classes.Ord a => GHC.Classes.Ord (Hedgehog.Internal.State.Concrete a) instance GHC.Classes.Ord Hedgehog.Internal.State.EnvironmentError instance GHC.Classes.Ord Hedgehog.Internal.State.Name instance GHC.Classes.Ord (Hedgehog.Internal.State.Symbolic a) instance (GHC.Classes.Ord a, Data.Functor.Classes.Ord1 v) => GHC.Classes.Ord (Hedgehog.Internal.State.Var a v) instance Data.Functor.Classes.Show1 Hedgehog.Internal.State.Concrete instance Data.Functor.Classes.Show1 Hedgehog.Internal.State.Symbolic instance GHC.Show.Show (Hedgehog.Internal.State.Action m state) instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.State.Concrete a) instance GHC.Show.Show Hedgehog.Internal.State.Environment instance GHC.Show.Show Hedgehog.Internal.State.EnvironmentError instance GHC.Show.Show Hedgehog.Internal.State.Name instance GHC.Show.Show (Hedgehog.Internal.State.Parallel m state) instance GHC.Show.Show (Hedgehog.Internal.State.Sequential m state) instance GHC.Show.Show (Hedgehog.Internal.State.Symbolic a) instance (GHC.Show.Show a, Data.Functor.Classes.Show1 v) => GHC.Show.Show (Hedgehog.Internal.State.Var a v) instance Barbies.Internal.TraversableB.TraversableB (Hedgehog.Internal.State.Var a) instance Data.Traversable.Traversable Hedgehog.Internal.State.Concrete module Hedgehog.Internal.Discovery newtype PropertySource PropertySource :: Pos String -> PropertySource [propertySource] :: PropertySource -> Pos String readProperties :: MonadIO m => String -> FilePath -> m (Map PropertyName PropertySource) findProperties :: String -> FilePath -> String -> Map PropertyName PropertySource readDeclaration :: MonadIO m => FilePath -> LineNo -> m (Maybe (String, Pos String)) data Pos a Pos :: !Position -> a -> Pos a [posPostion] :: Pos a -> !Position [posValue] :: Pos a -> a data Position Position :: !FilePath -> !LineNo -> !ColumnNo -> Position [_posPath] :: Position -> !FilePath [posLine] :: Position -> !LineNo [posColumn] :: Position -> !ColumnNo instance GHC.Classes.Eq Hedgehog.Internal.Discovery.Class instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Discovery.Classified a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Discovery.Pos a) instance GHC.Classes.Eq Hedgehog.Internal.Discovery.Position instance GHC.Classes.Eq Hedgehog.Internal.Discovery.PropertySource instance GHC.Base.Functor Hedgehog.Internal.Discovery.Pos instance GHC.Classes.Ord Hedgehog.Internal.Discovery.Class instance GHC.Classes.Ord a => GHC.Classes.Ord (Hedgehog.Internal.Discovery.Classified a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Hedgehog.Internal.Discovery.Pos a) instance GHC.Classes.Ord Hedgehog.Internal.Discovery.Position instance GHC.Classes.Ord Hedgehog.Internal.Discovery.PropertySource instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Hedgehog.Internal.Discovery.Pos a) instance GHC.Show.Show Hedgehog.Internal.Discovery.Class instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Discovery.Classified a) instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Discovery.Pos a) instance GHC.Show.Show Hedgehog.Internal.Discovery.Position instance GHC.Show.Show Hedgehog.Internal.Discovery.PropertySource module Hedgehog.Internal.TH type TExpQ a = CodeQ a -- | Discover all the properties in a module. -- -- Functions starting with prop_ are assumed to be properties. discover :: TExpQ Group discoverPrefix :: String -> TExpQ Group module Hedgehog.Internal.Config -- | Whether to render output using ANSI colors or not. data UseColor -- | Disable ANSI colors in report output. DisableColor :: UseColor -- | Enable ANSI colors in report output. EnableColor :: UseColor resolveColor :: MonadIO m => Maybe UseColor -> m UseColor -- | A splittable random number generator. data Seed Seed :: !Word64 -> !Word64 -> Seed [seedValue] :: Seed -> !Word64 -- | must be an odd number [seedGamma] :: Seed -> !Word64 resolveSeed :: MonadIO m => Maybe Seed -> m Seed -- | How verbose should the report output be. data Verbosity -- | Only display the summary of the test run. Quiet :: Verbosity -- | Display each property as it is running, as well as the summary. Normal :: Verbosity resolveVerbosity :: MonadIO m => Maybe Verbosity -> m Verbosity -- | The number of workers to use when running properties in parallel. newtype WorkerCount WorkerCount :: Int -> WorkerCount resolveWorkers :: MonadIO m => Maybe WorkerCount -> m WorkerCount -- | Where to start running a property's tests. data Skip -- | Don't skip anything. SkipNothing :: Skip -- | Skip to a specific test number. If it fails, shrink as normal. If it -- passes, move on to the next test. Coverage checks are disabled. -- -- We also need to count discards, since failing "after 7 tests" points -- at a different generated value than failing "after 7 tests and 5 -- discards". SkipToTest :: TestCount -> DiscardCount -> Skip -- | Skip to a specific test number and shrink state. If it fails, stop -- without shrinking further. If it passes, the property will pass -- without running any more tests. -- -- Due to implementation details, all intermediate shrink states - those -- on the direct path from the original test input to the target state - -- will be tested too, and their results discarded. SkipToShrink :: TestCount -> DiscardCount -> ShrinkPath -> Skip resolveSkip :: MonadIO m => Maybe Skip -> m Skip detectMark :: MonadIO m => m Bool detectColor :: MonadIO m => m UseColor detectSeed :: MonadIO m => m Seed detectVerbosity :: MonadIO m => m Verbosity detectWorkers :: MonadIO m => m WorkerCount detectSkip :: MonadIO m => m Skip instance GHC.Enum.Enum Hedgehog.Internal.Config.WorkerCount instance GHC.Classes.Eq Hedgehog.Internal.Config.UseColor instance GHC.Classes.Eq Hedgehog.Internal.Config.Verbosity instance GHC.Classes.Eq Hedgehog.Internal.Config.WorkerCount instance GHC.Real.Integral Hedgehog.Internal.Config.WorkerCount instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Config.UseColor instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Config.Verbosity instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Config.WorkerCount instance GHC.Num.Num Hedgehog.Internal.Config.WorkerCount instance GHC.Classes.Ord Hedgehog.Internal.Config.UseColor instance GHC.Classes.Ord Hedgehog.Internal.Config.Verbosity instance GHC.Classes.Ord Hedgehog.Internal.Config.WorkerCount instance GHC.Real.Real Hedgehog.Internal.Config.WorkerCount instance GHC.Show.Show Hedgehog.Internal.Config.UseColor instance GHC.Show.Show Hedgehog.Internal.Config.Verbosity instance GHC.Show.Show Hedgehog.Internal.Config.WorkerCount module Hedgehog.Internal.Report -- | A summary of all the properties executed. data Summary Summary :: !PropertyCount -> !PropertyCount -> !PropertyCount -> !PropertyCount -> !PropertyCount -> Summary [summaryWaiting] :: Summary -> !PropertyCount [summaryRunning] :: Summary -> !PropertyCount [summaryFailed] :: Summary -> !PropertyCount [summaryGaveUp] :: Summary -> !PropertyCount [summaryOK] :: Summary -> !PropertyCount -- | A report on a running or completed property test. data Report a Report :: !TestCount -> !DiscardCount -> !Coverage CoverCount -> !Seed -> !a -> Report a [reportTests] :: Report a -> !TestCount [reportDiscards] :: Report a -> !DiscardCount [reportCoverage] :: Report a -> !Coverage CoverCount [reportSeed] :: Report a -> !Seed [reportStatus] :: Report a -> !a -- | The status of a running property test. data Progress Running :: Progress Shrinking :: !FailureReport -> Progress -- | The status of a completed property test. -- -- In the case of a failure it provides the seed used for the test, the -- number of shrinks, and the execution log. data Result Failed :: !FailureReport -> Result GaveUp :: Result OK :: Result data FailureReport FailureReport :: !ShrinkCount -> !ShrinkPath -> !Maybe (Coverage CoverCount) -> ![FailedAnnotation] -> !Maybe Span -> !String -> !Maybe Diff -> ![String] -> FailureReport [failureShrinks] :: FailureReport -> !ShrinkCount [failureShrinkPath] :: FailureReport -> !ShrinkPath [failureCoverage] :: FailureReport -> !Maybe (Coverage CoverCount) [failureAnnotations] :: FailureReport -> ![FailedAnnotation] [failureLocation] :: FailureReport -> !Maybe Span [failureMessage] :: FailureReport -> !String [failureDiff] :: FailureReport -> !Maybe Diff [failureFootnotes] :: FailureReport -> ![String] data FailedAnnotation FailedAnnotation :: !Maybe Span -> !String -> FailedAnnotation [failedSpan] :: FailedAnnotation -> !Maybe Span [failedValue] :: FailedAnnotation -> !String data Style StyleDefault :: Style StyleAnnotation :: Style StyleFailure :: Style data Markup WaitingIcon :: Markup WaitingHeader :: Markup RunningIcon :: Markup RunningHeader :: Markup ShrinkingIcon :: Markup ShrinkingHeader :: Markup FailedIcon :: Markup FailedText :: Markup GaveUpIcon :: Markup GaveUpText :: Markup SuccessIcon :: Markup SuccessText :: Markup CoverageIcon :: Markup CoverageText :: Markup CoverageFill :: Markup DeclarationLocation :: Markup StyledLineNo :: !Style -> Markup StyledBorder :: !Style -> Markup StyledSource :: !Style -> Markup AnnotationGutter :: Markup AnnotationValue :: Markup FailureArrows :: Markup FailureGutter :: Markup FailureMessage :: Markup DiffPrefix :: Markup DiffInfix :: Markup DiffSuffix :: Markup DiffSame :: Markup DiffRemoved :: Markup DiffAdded :: Markup ReproduceHeader :: Markup ReproduceGutter :: Markup ReproduceSource :: Markup data Config Config :: Context -> Bool -> Bool -> Bool -> PrintPrefixIcons -> Config [configContext] :: Config -> Context [configPrintFailedAtLocation] :: Config -> Bool [configPrintShrinkPath] :: Config -> Bool [configPrintReproduceMessage] :: Config -> Bool [configPrintPrefixIcons] :: Config -> PrintPrefixIcons defaultConfig :: Config data Context FullContext :: Context Context :: Lines -> Context data Lines -- | Whether to add icons to the start of important output lines or not. data PrintPrefixIcons -- | Do not add icons to the start of important output lines. DisablePrefixIcons :: PrintPrefixIcons -- | Add icons to the start of important output lines. EnablePrefixIcons :: PrintPrefixIcons renderProgress :: MonadIO m => UseColor -> Maybe PropertyName -> Report Progress -> m String renderResult :: MonadIO m => UseColor -> Maybe PropertyName -> Report Result -> m String renderResultWith :: MonadIO m => Config -> UseColor -> Maybe PropertyName -> Report Result -> m String renderSummary :: MonadIO m => UseColor -> Summary -> m String renderDoc :: MonadIO m => UseColor -> Doc Markup -> m String ppProgress :: MonadIO m => Maybe PropertyName -> Report Progress -> m (Doc Markup) ppResult :: MonadIO m => Maybe PropertyName -> Report Result -> m (Doc Markup) ppResultWith :: MonadIO m => Config -> Maybe PropertyName -> Report Result -> m (Doc Markup) ppSummary :: MonadIO m => Summary -> m (Doc Markup) -- | Construct a summary from a single result. fromResult :: Result -> Summary mkFailure :: ShrinkCount -> ShrinkPath -> Maybe (Coverage CoverCount) -> Maybe Span -> String -> Maybe Diff -> [Log] -> FailureReport instance GHC.Classes.Eq Hedgehog.Internal.Report.Config instance GHC.Classes.Eq Hedgehog.Internal.Report.Context instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Report.Declaration a) instance GHC.Classes.Eq Hedgehog.Internal.Report.FailedAnnotation instance GHC.Classes.Eq Hedgehog.Internal.Report.FailureReport instance GHC.Classes.Eq a => GHC.Classes.Eq (Hedgehog.Internal.Report.Line a) instance GHC.Classes.Eq Hedgehog.Internal.Report.Lines instance GHC.Classes.Eq Hedgehog.Internal.Report.Markup instance GHC.Classes.Eq Hedgehog.Internal.Report.PrintPrefixIcons instance GHC.Classes.Eq Hedgehog.Internal.Report.Progress instance GHC.Classes.Eq Hedgehog.Internal.Report.Result instance GHC.Classes.Eq Hedgehog.Internal.Report.Style instance Data.Foldable.Foldable Hedgehog.Internal.Report.Report instance GHC.Base.Functor Hedgehog.Internal.Report.Declaration instance GHC.Base.Functor Hedgehog.Internal.Report.Line instance GHC.Base.Functor Hedgehog.Internal.Report.Report instance GHC.Base.Monoid Hedgehog.Internal.Report.ColumnWidth instance GHC.Base.Monoid Hedgehog.Internal.Report.Summary instance GHC.Num.Num Hedgehog.Internal.Report.Lines instance GHC.Classes.Ord a => GHC.Classes.Ord (Hedgehog.Internal.Report.Declaration a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Hedgehog.Internal.Report.Line a) instance GHC.Classes.Ord Hedgehog.Internal.Report.Markup instance GHC.Classes.Ord Hedgehog.Internal.Report.Style instance GHC.Base.Semigroup Hedgehog.Internal.Report.ColumnWidth instance GHC.Base.Semigroup Hedgehog.Internal.Report.Style instance GHC.Base.Semigroup Hedgehog.Internal.Report.Summary instance GHC.Show.Show Hedgehog.Internal.Report.Config instance GHC.Show.Show Hedgehog.Internal.Report.Context instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Report.Declaration a) instance GHC.Show.Show Hedgehog.Internal.Report.FailedAnnotation instance GHC.Show.Show Hedgehog.Internal.Report.FailureReport instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Report.Line a) instance GHC.Show.Show Hedgehog.Internal.Report.Lines instance GHC.Show.Show Hedgehog.Internal.Report.Markup instance GHC.Show.Show Hedgehog.Internal.Report.PrintPrefixIcons instance GHC.Show.Show Hedgehog.Internal.Report.Progress instance GHC.Show.Show a => GHC.Show.Show (Hedgehog.Internal.Report.Report a) instance GHC.Show.Show Hedgehog.Internal.Report.Result instance GHC.Show.Show Hedgehog.Internal.Report.Style instance GHC.Show.Show Hedgehog.Internal.Report.Summary instance Data.Traversable.Traversable Hedgehog.Internal.Report.Report module Hedgehog.Internal.Queue newtype TaskIndex TaskIndex :: Int -> TaskIndex newtype TasksRemaining TasksRemaining :: Int -> TasksRemaining runTasks :: WorkerCount -> [a] -> (TasksRemaining -> TaskIndex -> a -> IO b) -> (b -> IO ()) -> (b -> IO ()) -> (b -> IO c) -> IO [c] finalizeTask :: MonadIO m => MVar (TaskIndex, Map TaskIndex (IO ())) -> TaskIndex -> IO () -> m () runActiveFinalizers :: MonadIO m => MVar (TaskIndex, Map TaskIndex (IO ())) -> m () dequeueMVar :: MVar [(TaskIndex, a)] -> (TasksRemaining -> TaskIndex -> a -> IO b) -> IO (Maybe (TaskIndex, b)) -- | Update the number of capabilities but never set it lower than it -- already is. updateNumCapabilities :: WorkerCount -> IO () instance GHC.Enum.Enum Hedgehog.Internal.Queue.TaskIndex instance GHC.Classes.Eq Hedgehog.Internal.Queue.TaskIndex instance GHC.Num.Num Hedgehog.Internal.Queue.TaskIndex instance GHC.Classes.Ord Hedgehog.Internal.Queue.TaskIndex module Hedgehog.Internal.Runner -- | Check a property. check :: MonadIO m => Property -> m Bool -- | Check a property using a specific size and seed. recheck :: MonadIO m => Size -> Seed -> Property -> m () recheckAt :: MonadIO m => Seed -> Skip -> Property -> m () -- | Configuration for a property test run. data RunnerConfig RunnerConfig :: !Maybe WorkerCount -> !Maybe UseColor -> !Maybe Seed -> !Maybe Verbosity -> RunnerConfig -- | The number of property tests to run concurrently. Nothing means -- use one worker per processor. [runnerWorkers] :: RunnerConfig -> !Maybe WorkerCount -- | Whether to use colored output or not. Nothing means detect from -- the environment. [runnerColor] :: RunnerConfig -> !Maybe UseColor -- | The seed to use. Nothing means detect from the environment. [runnerSeed] :: RunnerConfig -> !Maybe Seed -- | How verbose to be in the runner output. Nothing means detect -- from the environment. [runnerVerbosity] :: RunnerConfig -> !Maybe Verbosity -- | Check a group of properties in parallel. -- -- Warning: although this check function runs tests faster than -- checkSequential, it should be noted that it may cause -- problems with properties that are not self-contained. For -- example, if you have a group of tests which all use the same -- database table, you may find that they interfere with each -- other when being run in parallel. -- -- Using Template Haskell for property discovery: -- --
-- tests :: IO Bool -- tests = -- checkParallel $$(discover) ---- -- With manually specified properties: -- --
-- tests :: IO Bool
-- tests =
-- checkParallel $ Group "Test.Example" [
-- ("prop_reverse", prop_reverse)
-- ]
--
checkParallel :: MonadIO m => Group -> m Bool
-- | Check a group of properties sequentially.
--
-- Using Template Haskell for property discovery:
--
-- -- tests :: IO Bool -- tests = -- checkSequential $$(discover) ---- -- With manually specified properties: -- --
-- tests :: IO Bool
-- tests =
-- checkSequential $ Group "Test.Example" [
-- ("prop_reverse", prop_reverse)
-- ]
--
checkSequential :: MonadIO m => Group -> m Bool
-- | Check a group of properties using the specified runner config.
checkGroup :: MonadIO m => RunnerConfig -> Group -> m Bool
checkReport :: (MonadIO m, MonadCatch m) => PropertyConfig -> Size -> Seed -> PropertyT m () -> (Report Progress -> m ()) -> m (Report Result)
checkRegion :: MonadIO m => Region -> UseColor -> Maybe PropertyName -> Size -> Seed -> Property -> m (Report Result)
checkNamed :: MonadIO m => Region -> UseColor -> Maybe PropertyName -> Maybe Seed -> Property -> m (Report Result)
instance GHC.Classes.Eq Hedgehog.Internal.Runner.RunnerConfig
instance Language.Haskell.TH.Syntax.Lift Hedgehog.Internal.Runner.RunnerConfig
instance GHC.Classes.Ord Hedgehog.Internal.Runner.RunnerConfig
instance GHC.Show.Show Hedgehog.Internal.Runner.RunnerConfig
module Hedgehog.Gen
-- | Apply a shrinking function to a generator.
--
-- This will give the generator additional shrinking options, while
-- keeping the existing shrinks intact.
shrink :: MonadGen m => (a -> [a]) -> m a -> m a
-- | Throw away a generator's shrink tree.
prune :: MonadGen m => m a -> m a
-- | Make a generator smaller by scaling its size parameter.
small :: MonadGen m => m a -> m a
-- | Adjust the size parameter by transforming it with the given function.
scale :: (HasCallStack, MonadGen m) => (Size -> Size) -> m a -> m a
-- | Override the size parameter. Returns a generator which uses the given
-- size instead of the runtime-size parameter.
resize :: MonadGen m => Size -> m a -> m a
-- | Construct a generator that depends on the size parameter.
sized :: MonadGen m => (Size -> m a) -> m a
-- | Generates a random integral number in the given
-- [inclusive,inclusive] range.
--
-- When the generator tries to shrink, it will shrink towards the
-- origin of the specified Range.
--
-- For example, the following generator will produce a number between
-- 1970 and 2100, but will shrink towards
-- 2000:
--
-- -- integral (Range.constantFrom 2000 1970 2100) :: Gen Int ---- -- Some sample outputs from this generator might look like: -- --
-- === Outcome === -- 1973 -- === Shrinks === -- 2000 -- 1987 -- 1980 -- 1976 -- 1974 ---- --
-- === Outcome === -- 2061 -- === Shrinks === -- 2000 -- 2031 -- 2046 -- 2054 -- 2058 -- 2060 --integral :: (MonadGen m, Integral a) => Range a -> m a -- | Generates a random integral number in the [inclusive,inclusive] range. -- -- This generator does not shrink. integral_ :: (MonadGen m, Integral a) => Range a -> m a -- | Generates a random machine integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int :: MonadGen m => Range Int -> m Int -- | Generates a random 8-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int8 :: MonadGen m => Range Int8 -> m Int8 -- | Generates a random 16-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int16 :: MonadGen m => Range Int16 -> m Int16 -- | Generates a random 32-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int32 :: MonadGen m => Range Int32 -> m Int32 -- | Generates a random 64-bit integer in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. int64 :: MonadGen m => Range Int64 -> m Int64 -- | Generates a random machine word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word :: MonadGen m => Range Word -> m Word -- | Generates a random byte in the given [inclusive,inclusive] -- range. -- -- This is a specialization of integral, offered for -- convenience. word8 :: MonadGen m => Range Word8 -> m Word8 -- | Generates a random 16-bit word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word16 :: MonadGen m => Range Word16 -> m Word16 -- | Generates a random 32-bit word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word32 :: MonadGen m => Range Word32 -> m Word32 -- | Generates a random 64-bit word in the given -- [inclusive,inclusive] range. -- -- This is a specialization of integral, offered for -- convenience. word64 :: MonadGen m => Range Word64 -> m Word64 -- | Generates a random floating-point number in the -- [inclusive,exclusive) range. -- -- This generator works the same as integral, but for floating -- point numbers. realFloat :: (MonadGen m, RealFloat a) => Range a -> m a -- | Generates a random fractional number in the [inclusive,exclusive) -- range. -- -- This generator does not shrink. realFrac_ :: (MonadGen m, RealFrac a) => Range a -> m a -- | Generates a random floating-point number in the -- [inclusive,exclusive) range. -- -- This is a specialization of realFloat, offered for -- convenience. float :: MonadGen m => Range Float -> m Float -- | Generates a random floating-point number in the -- [inclusive,exclusive) range. -- -- This is a specialization of realFloat, offered for -- convenience. double :: MonadGen m => Range Double -> m Double -- | Generates an element from an enumeration. -- -- This generator shrinks towards the first argument. -- -- For example: -- --
-- enum 'a' 'z' :: Gen Char --enum :: (MonadGen m, Enum a) => a -> a -> m a -- | Generates a random value from a bounded enumeration. -- -- This generator shrinks towards minBound. -- -- For example: -- --
-- enumBounded :: Gen Bool ---- -- This is implemented in terms of the Enum class, and thus may -- be partial for integral types larger than Int, e.g. -- Word64. enumBounded :: (MonadGen m, Enum a, Bounded a) => m a -- | Generates a random boolean. -- -- This generator shrinks to False. -- -- This is a specialization of enumBounded, offered for -- convenience. bool :: MonadGen m => m Bool -- | Generates a random boolean. -- -- This generator does not shrink. bool_ :: MonadGen m => m Bool -- | Generates an ASCII binit: '0'..'1' binit :: MonadGen m => m Char -- | Generates an ASCII octit: '0'..'7' octit :: MonadGen m => m Char -- | Generates an ASCII digit: '0'..'9' digit :: MonadGen m => m Char -- | Generates an ASCII hexit: '0'..'9', 'a'..'f', 'A'..'F' hexit :: MonadGen m => m Char -- | Generates an ASCII lowercase letter: 'a'..'z' lower :: MonadGen m => m Char -- | Generates an ASCII uppercase letter: 'A'..'Z' upper :: MonadGen m => m Char -- | Generates an ASCII letter: 'a'..'z', 'A'..'Z' alpha :: MonadGen m => m Char -- | Generates an ASCII letter or digit: 'a'..'z', 'A'..'Z', -- '0'..'9' alphaNum :: MonadGen m => m Char -- | Generates an ASCII character: '0'..'127' ascii :: MonadGen m => m Char -- | Generates a Latin-1 character: '0'..'255' latin1 :: MonadGen m => m Char -- | Generates a Unicode character, excluding noncharacters and invalid -- standalone surrogates: '0'..'1114111' (excluding '55296'..'57343', -- '65534', '65535') unicode :: MonadGen m => m Char -- | Generates a Unicode character, including noncharacters and invalid -- standalone surrogates: '0'..'1114111' unicodeAll :: MonadGen m => m Char -- | Generates a string using Range to determine the length. -- -- This is a specialization of list, offered for -- convenience. string :: MonadGen m => Range Int -> m Char -> m String -- | Generates a string using Range to determine the length. text :: MonadGen m => Range Int -> m Char -> m Text -- | Generates a UTF-8 encoded string, using Range to determine the -- length. utf8 :: MonadGen m => Range Int -> m Char -> m ByteString -- | Generates a random ByteString, using Range to determine -- the length. bytes :: MonadGen m => Range Int -> m ByteString -- | Trivial generator that always produces the same element. -- -- This is another name for pure / return. constant :: MonadGen m => a -> m a -- | Randomly selects one of the elements in the list. -- -- This generator shrinks towards the first element in the list. -- -- The input list must be non-empty. element :: (HasCallStack, Foldable f, MonadGen m) => f a -> m a -- | Randomly selects one of the generators in the list. -- -- This generator shrinks towards the first generator in the list. -- -- The input list must be non-empty. choice :: (HasCallStack, MonadGen m) => [m a] -> m a -- | Uses a weighted distribution to randomly select one of the generators -- in the list. -- -- This generator shrinks towards the first generator in the list. -- -- The input list must be non-empty. frequency :: (HasCallStack, MonadGen m) => [(Int, m a)] -> m a -- | Modifies combinators which choose from a list of generators, like -- choice or frequency, so that they can be used in -- recursive scenarios. -- -- This combinator modifies its target to select one of the generators in -- either the non-recursive or the recursive list. When a selection is -- made from the recursive list, the Size is halved. When the -- Size gets to one or less, selections are no longer made from -- the recursive list, this ensures termination. -- -- A good example of where this might be useful is abstract syntax trees: -- --
-- data Expr = -- Var String -- | Lam String Expr -- | App Expr Expr -- -- -- Assuming we have a name generator -- genName :: MonadGen m => m String -- -- -- We can write a generator for expressions -- genExpr :: MonadGen m => m Expr -- genExpr = -- Gen.recursive Gen.choice [ -- -- non-recursive generators -- Var <$> genName -- ] [ -- -- recursive generators -- Gen.subtermM genExpr (x -> Lam <$> genName <*> pure x) -- , Gen.subterm2 genExpr genExpr App -- ] ---- -- If we wrote the above example using only choice, it is likely -- that it would fail to terminate. This is because for every call to -- genExpr, there is a 2 in 3 chance that we will recurse again. recursive :: MonadGen m => ([m a] -> m a) -> [m a] -> [m a] -> m a -- | Discards the whole generator. discard :: MonadGen m => m a -- | Generates a value that satisfies a predicate. -- -- Shrinks of the generated value will also satisfy the predicate. From -- the original generator's shrink tree, any values that fail the -- predicate will be removed, but any subsequent shrinks that satisfy it -- will be retained. Compared to filter, shrinking may be slower -- but will be optimal. -- -- It's possible that the predicate will never pass, or will only pass at -- a larger size than we're currently running at. To avoid looping -- forever, we limit the number of retries, and grow the size with each -- retry. If we retry too many times then the whole generator is -- discarded. filter :: (MonadGen m, GenBase m ~ Identity) => (a -> Bool) -> m a -> m a -- | Generates a value that satisfies a predicate. -- -- Shrinks of the generated value will also satisfy the predicate. From -- the original generator's shrink tree, any values that fail the -- predicate will be removed, along with their subsequent shrinks. -- Compared to filter, shrinking may be faster but may also be -- less optimal. -- -- The type is also more general, because the shrink behavior from -- filter would force the entire shrink tree to be evaluated when -- applied to an impure tree. -- -- This is essentially: -- --
-- filterT p gen = mfilter p gen <|> filterT p gen ---- -- But that could loop forever, if the predicate will never pass or will -- only pass at a larger size than we're currently running at. We differ -- from the above in keeping some state to avoid that. We limit the -- number of retries, and grow the size with each retry. If we retry too -- many times then the whole generator is discarded. filterT :: MonadGen m => (a -> Bool) -> m a -> m a -- | Generates a value which is the result of the given function returning -- a Just. -- -- The original generator's shrink tree will be retained, with values -- returning Nothing removed. Subsequent shrinks of those values -- will be retained. Compared to mapMaybeT, shrinking may be -- slower but will be optimal. -- -- It's possible that the function will never return Just, or will -- only do so a larger size than we're currently running at. To avoid -- looping forever, we limit the number of retries, and grow the size -- with each retry. If we retry too many times then the whole generator -- is discarded. mapMaybe :: (MonadGen m, GenBase m ~ Identity) => (a -> Maybe b) -> m a -> m b -- | Generates a value which is the result of the given function returning -- a Just. -- -- The original generator's shrink tree will be retained, with values -- returning Nothing removed. Subsequent shrinks of those values -- will be retained. Compared to mapMaybeT, shrinking may be -- slower but will be optimal. -- -- The type is also more general, because the shrink behavior from -- mapMaybe would force the entire shrink tree to be evaluated -- when applied to an impure tree. -- -- It's possible that the function will never return Just, or will -- only do so a larger size than we're currently running at. To avoid -- looping forever, we limit the number of retries, and grow the size -- with each retry. If we retry too many times then the whole generator -- is discarded. mapMaybeT :: MonadGen m => (a -> Maybe b) -> m a -> m b -- | Runs a Maybe generator until it produces a Just. -- -- This is implemented using filter and has the same -- caveats. just :: (MonadGen m, GenBase m ~ Identity) => m (Maybe a) -> m a -- | Runs a Maybe generator until it produces a Just. -- -- This is implemented using filter and has the same -- caveats. justT :: MonadGen m => m (Maybe a) -> m a -- | Generates a Nothing some of the time. maybe :: MonadGen m => m a -> m (Maybe a) -- | Generates either an a or a b. -- -- As the size grows, this generator generates Rights more often -- than Lefts. either :: MonadGen m => m a -> m b -> m (Either a b) -- | Generates either an a or a b, without bias. -- -- This generator generates as many Rights as it does -- Lefts. either_ :: MonadGen m => m a -> m b -> m (Either a b) -- | Generates a list using a Range to determine the length. list :: MonadGen m => Range Int -> m a -> m [a] -- | Generates a seq using a Range to determine the length. seq :: MonadGen m => Range Int -> m a -> m (Seq a) -- | Generates a non-empty list using a Range to determine the -- length. nonEmpty :: MonadGen m => Range Int -> m a -> m (NonEmpty a) -- | Generates a set using a Range to determine the length. -- -- This may fail to generate anything if the element generator -- cannot produce a large enough number of unique items to satify -- the required set size. set :: (MonadGen m, Ord a) => Range Int -> m a -> m (Set a) -- | Generates a map using a Range to determine the length. -- -- This may fail to generate anything if the keys produced by the -- generator do not account for a large enough number of unique -- items to satify the required map size. map :: (MonadGen m, Ord k) => Range Int -> m (k, v) -> m (Map k v) -- | Freeze the size and seed used by a generator, so we can inspect the -- value which it will produce. -- -- This is used for implementing list and subtermMVec. It -- allows us to shrink the list itself before trying to shrink the values -- inside the list. freeze :: MonadGen m => m a -> m (a, m a) -- | Constructs a generator from a sub-term generator. -- -- Shrinks to the sub-term if possible. subterm :: MonadGen m => m a -> (a -> a) -> m a -- | Constructs a generator from a sub-term generator. -- -- Shrinks to the sub-term if possible. subtermM :: MonadGen m => m a -> (a -> m a) -> m a -- | Constructs a generator from two sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subterm2 :: MonadGen m => m a -> m a -> (a -> a -> a) -> m a -- | Constructs a generator from two sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subtermM2 :: MonadGen m => m a -> m a -> (a -> a -> m a) -> m a -- | Constructs a generator from three sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subterm3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> a) -> m a -- | Constructs a generator from three sub-term generators. -- -- Shrinks to one of the sub-terms if possible. subtermM3 :: MonadGen m => m a -> m a -> m a -> (a -> a -> a -> m a) -> m a -- | Generates a random subsequence of a list. -- -- For example: -- --
-- Gen.print (Gen.subsequence [1..5]) ---- --
-- === Outcome === -- [1,2,4] -- === Shrinks === -- [] -- [2,4] -- [1,4] -- [1,2] --subsequence :: MonadGen m => [a] -> m [a] -- | Generates a random subset of a set. -- -- This shrinks towards the empty set. subset :: MonadGen m => Set a -> m (Set a) -- | Generates a random permutation of a list. -- -- This shrinks towards the order of the list being identical to the -- input list. shuffle :: MonadGen m => [a] -> m [a] -- | Generates a sequence of actions from an initial model state and set of -- commands. sequential :: forall gen (m :: Type -> Type) state. (MonadGen gen, MonadTest m) => Range Int -> (forall (v :: Type -> Type). () => state v) -> [Command gen m state] -> gen (Sequential m state) -- | Given the initial model state and set of commands, generates prefix -- actions to be run sequentially, followed by two branches to be run in -- parallel. parallel :: forall gen (m :: Type -> Type) state. (MonadGen gen, MonadTest m) => Range Int -> Range Int -> (forall (v :: Type -> Type). () => state v) -> [Command gen m state] -> gen (Parallel m state) -- | Generate a sample from a generator. -- -- This function is useful for examining a Gen in GHCi or other -- contexts. It is not appropriate for use in a test suite directly. You -- will only get a single sample from this function, and it will not give -- you a property test. The seed is random, so the test is not -- deterministic. -- -- If you only want a single test to run, then use withTests -- 1: -- --
-- prop_OnlyRunOnce :: Property -- prop_OnlyRunOnce = -- withTests 1 $ property $ do -- i <- Gen.int -- i /== 0 --sample :: (HasCallStack, MonadIO m) => Gen a -> m a -- | Run a generator with a random seed and print the outcome, and the -- first level of shrinks. -- --
-- Gen.print (Gen.enum 'a' 'f') ---- --
-- === Outcome === -- 'd' -- === Shrinks === -- 'a' -- 'b' -- 'c' --print :: (MonadIO m, Show a) => Gen a -> m () -- | Run a generator with a random seed and print the resulting shrink -- tree. -- --
-- Gen.printTree (Gen.enum 'a' 'f') ---- --
-- 'd' -- ├╼'a' -- ├╼'b' -- │ └╼'a' -- └╼'c' -- ├╼'a' -- └╼'b' -- └╼'a' ---- -- This may not terminate when the tree is very large. printTree :: (MonadIO m, Show a) => Gen a -> m () -- | Print the value produced by a generator, and the first level of -- shrinks, for the given size and seed. -- -- Use print to generate a value from a random seed. printWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () -- | Print the shrink tree produced by a generator, for the given size and -- seed. -- -- Use printTree to generate a value from a random seed. printTreeWith :: (MonadIO m, Show a) => Size -> Seed -> Gen a -> m () -- | This module includes almost everything you need to get started writing -- property tests with Hedgehog. -- -- It is designed to be used alongside Hedgehog.Gen and -- Hedgehog.Range, which should be imported qualified. You also -- need to enable Template Haskell so the Hedgehog test runner can find -- your properties. -- --
-- {-# LANGUAGE TemplateHaskell #-}
--
-- import Hedgehog
-- import qualified Hedgehog.Gen as Gen
-- import qualified Hedgehog.Range as Range
--
--
-- Once you have your imports set up, you can write a simple property:
--
-- -- prop_reverse :: Property -- prop_reverse = -- property $ do -- xs <- forAll $ Gen.list (Range.linear 0 100) Gen.alpha -- reverse (reverse xs) === xs ---- -- And add the Template Haskell splice which will discover your -- properties: -- --
-- tests :: IO Bool -- tests = -- checkParallel $$(discover) ---- -- If you prefer to avoid macros, you can specify the group of properties -- to run manually instead: -- --
-- {-# LANGUAGE OverloadedStrings #-}
--
-- tests :: IO Bool
-- tests =
-- checkParallel $ Group "Test.Example" [
-- ("prop_reverse", prop_reverse)
-- ]
--
--
-- You can then load the module in GHCi, and run it:
--
-- -- λ tests -- ━━━ Test.Example ━━━ -- ✓ prop_reverse passed 100 tests. --module Hedgehog -- | A property test, along with some configurable limits like how many -- times to run the test. data Property -- | The property monad transformer allows both the generation of test -- inputs and the assertion of expectations. data PropertyT (m :: Type -> Type) a -- | A named collection of property tests. data Group Group :: !GroupName -> ![(PropertyName, Property)] -> Group [groupName] :: Group -> !GroupName [groupProperties] :: Group -> ![(PropertyName, Property)] -- | The name of a property. -- -- Should be constructed using OverloadedStrings: -- --
-- "apples" :: PropertyName --data PropertyName -- | The name of a group of properties. -- -- Should be constructed using OverloadedStrings: -- --
-- "fruit" :: GroupName --data GroupName -- | Creates a property with the default configuration. property :: HasCallStack => PropertyT IO () -> Property -- | Lift a test in to a property. -- -- Because both TestT and PropertyT have MonadTest -- instances, this function is not often required. It can however be -- useful for writing functions directly in TestT and thus gaining -- a MonadTransControl instance at the expense of not being able -- to generate additional inputs using forAll. -- -- An example where this is useful is parallel state machine testing, as -- executeParallel requires MonadBaseControl IO in -- order to be able to spawn threads in MonadTest. test :: forall (m :: Type -> Type) a. Monad m => TestT m a -> PropertyT m a -- | Generates a random input for the test by running the provided -- generator. forAll :: forall (m :: Type -> Type) a. (Monad m, Show a, HasCallStack) => Gen a -> PropertyT m a -- | Generates a random input for the test by running the provided -- generator. -- -- This is a the same as forAll but allows the user to provide -- a custom rendering function. This is useful for values which -- don't have a Show instance. forAllWith :: forall (m :: Type -> Type) a. (Monad m, HasCallStack) => (a -> String) -> Gen a -> PropertyT m a -- | Discards the current test entirely. discard :: forall (m :: Type -> Type) a. Monad m => PropertyT m a -- | Check a property. check :: MonadIO m => Property -> m Bool -- | Check a property using a specific size and seed. recheck :: MonadIO m => Size -> Seed -> Property -> m () recheckAt :: MonadIO m => Seed -> Skip -> Property -> m () -- | Discover all the properties in a module. -- -- Functions starting with prop_ are assumed to be properties. discover :: TExpQ Group discoverPrefix :: String -> TExpQ Group -- | Check a group of properties in parallel. -- -- Warning: although this check function runs tests faster than -- checkSequential, it should be noted that it may cause -- problems with properties that are not self-contained. For -- example, if you have a group of tests which all use the same -- database table, you may find that they interfere with each -- other when being run in parallel. -- -- Using Template Haskell for property discovery: -- --
-- tests :: IO Bool -- tests = -- checkParallel $$(discover) ---- -- With manually specified properties: -- --
-- tests :: IO Bool
-- tests =
-- checkParallel $ Group "Test.Example" [
-- ("prop_reverse", prop_reverse)
-- ]
--
checkParallel :: MonadIO m => Group -> m Bool
-- | Check a group of properties sequentially.
--
-- Using Template Haskell for property discovery:
--
-- -- tests :: IO Bool -- tests = -- checkSequential $$(discover) ---- -- With manually specified properties: -- --
-- tests :: IO Bool
-- tests =
-- checkSequential $ Group "Test.Example" [
-- ("prop_reverse", prop_reverse)
-- ]
--
checkSequential :: MonadIO m => Group -> m Bool
-- | The acceptable occurrence of false positives
--
-- Example, Confidence 10^9 would mean that you'd accept a false
-- positive for 1 in 10^9 tests.
data Confidence
verifiedTermination :: Property -> Property
-- | Make sure that the result is statistically significant in accordance
-- to the passed Confidence
withConfidence :: Confidence -> Property -> Property
-- | Set the number of times a property should be executed before it is
-- considered successful.
--
-- If you have a test that does not involve any generators and thus does
-- not need to run repeatedly, you can use withTests 1 to define
-- a property that will only be checked once.
withTests :: TestLimit -> Property -> Property
-- | The number of successful tests that need to be run before a property
-- test is considered successful.
--
-- Can be constructed using numeric literals:
--
-- -- 200 :: TestLimit --data TestLimit -- | Set the number of times a property is allowed to discard before the -- test runner gives up. withDiscards :: DiscardLimit -> Property -> Property -- | The number of discards to allow before giving up. -- -- Can be constructed using numeric literals: -- --
-- 10000 :: DiscardLimit --data DiscardLimit -- | Set the number of times a property is allowed to shrink before the -- test runner gives up and prints the counterexample. withShrinks :: ShrinkLimit -> Property -> Property -- | The number of shrinks to try before giving up on shrinking. -- -- Can be constructed using numeric literals: -- --
-- 1000 :: ShrinkLimit --data ShrinkLimit -- | Set the number of times a property will be executed for each shrink -- before the test runner gives up and tries a different shrink. See -- ShrinkRetries for more information. withRetries :: ShrinkRetries -> Property -> Property -- | The number of times to re-run a test during shrinking. This is useful -- if you are testing something which fails non-deterministically and you -- want to increase the change of getting a good shrink. -- -- If you are doing parallel state machine testing, you should probably -- set shrink retries to something like 10. This will mean that -- during shrinking, a parallel test case requires 10 successful runs -- before it is passes and we try a different shrink. -- -- Can be constructed using numeric literals: -- --
-- 0 :: ShrinkRetries --data ShrinkRetries -- | Set the target that a property will skip to before it starts to run. withSkip :: Skip -> Property -> Property -- | Where to start running a property's tests. data Skip -- | Generator for random values of a. type Gen = GenT Identity -- | Monad transformer which can generate random values of a. data GenT (m :: Type -> Type) a -- | Class of monads which can generate input data for tests. class (Monad m, Monad GenBase m) => MonadGen (m :: Type -> Type) where { type GenBase (m :: Type -> Type) :: Type -> Type; } -- | Extract a GenT from a MonadGen. toGenT :: MonadGen m => m a -> GenT (GenBase m) a -- | Lift a GenT in to a MonadGen. fromGenT :: MonadGen m => GenT (GenBase m) a -> m a -- | A range describes the bounds of a number to generate, which may or may -- not be dependent on a Size. -- -- The constructor takes an origin between the lower and upper bound, and -- a function from Size to bounds. As the size goes towards -- 0, the values go towards the origin. data Range a -- | Tests are parameterized by the size of the randomly-generated data. -- The meaning of a Size value depends on the particular generator -- used, but it must always be a number between 0 and 99 inclusive. newtype Size Size :: Int -> Size [unSize] :: Size -> Int -- | A splittable random number generator. data Seed Seed :: !Word64 -> !Word64 -> Seed [seedValue] :: Seed -> !Word64 -- | must be an odd number [seedGamma] :: Seed -> !Word64 -- | A test monad allows the assertion of expectations. type Test = TestT Identity -- | A test monad transformer allows the assertion of expectations. data TestT (m :: Type -> Type) a class Monad m => MonadTest (m :: Type -> Type) liftTest :: MonadTest m => Test a -> m a -- | Annotates the source code with a message that might be useful for -- debugging a test failure. annotate :: (MonadTest m, HasCallStack) => String -> m () -- | Annotates the source code with a value that might be useful for -- debugging a test failure. annotateShow :: (MonadTest m, Show a, HasCallStack) => a -> m () -- | Logs a message to be displayed as additional information in the footer -- of the failure report. footnote :: MonadTest m => String -> m () -- | Logs a value to be displayed as additional information in the footer -- of the failure report. footnoteShow :: (MonadTest m, Show a) => a -> m () -- | Another name for pure (). success :: MonadTest m => m () -- | Causes a test to fail. failure :: (MonadTest m, HasCallStack) => m a -- | Fails the test if the condition provided is False. assert :: (MonadTest m, HasCallStack) => Bool -> m () -- | Fails the test and shows a git-like diff if the comparison operation -- evaluates to False when applied to its arguments. -- -- The comparison function is the second argument, which may be -- counter-intuitive to Haskell programmers. However, it allows operators -- to be written infix for easy reading: -- --
-- diff y (<) 87 -- diff x (<=) r ---- -- This function behaves like the unix diff tool, which gives a -- 0 exit code if the compared files are identical, or a 1 exit code code -- otherwise. Like unix diff, if the arguments fail the -- comparison, a /diff is shown. diff :: (MonadTest m, Show a, Show b, HasCallStack) => a -> (a -> b -> Bool) -> b -> m () -- | Fails the test if the two arguments provided are not equal. (===) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m () infix 4 === -- | Fails the test if the two arguments provided are equal. (/==) :: (MonadTest m, Eq a, Show a, HasCallStack) => a -> a -> m () infix 4 /== -- | Test that a pair of encode / decode functions are compatible. -- -- Given a printer from some type a -> b, and a parser with a -- potential failure case b -> f a. Ensure that a valid -- a round trips through the "print" and "parse" to yield the -- same a. -- -- For example, types should have tripping Read and -- Show instances: -- --
-- trippingShowRead :: (Show a, Read a, Eq a, MonadTest m) => a -> m () -- trippingShowRead a = tripping a show readEither --tripping :: (MonadTest m, Applicative f, Show b, Show (f a), Eq (f a), HasCallStack) => a -> (a -> b) -> (b -> f a) -> m () -- | Fails the test if the value throws an exception when evaluated to weak -- head normal form (WHNF). eval :: (MonadTest m, HasCallStack) => a -> m a -- | Fails the test if the value throws an exception when evaluated to -- normal form (NF). evalNF :: (MonadTest m, NFData a, HasCallStack) => a -> m a -- | Fails the test if the action throws an exception. -- -- The benefit of using this over simply letting the exception bubble -- up is that the location of the closest evalM will be -- shown in the output. evalM :: (MonadTest m, MonadCatch m, HasCallStack) => m a -> m a -- | Fails the test if the IO action throws an exception. -- -- The benefit of using this over liftIO is that the location -- of the exception will be shown in the output. evalIO :: (MonadTest m, MonadIO m, HasCallStack) => IO a -> m a -- | Fails the test if the Either is Left, otherwise returns -- the value in the Right. evalEither :: (MonadTest m, Show x, HasCallStack) => Either x a -> m a -- | Fails the test if the action throws an exception, or if the -- Either is Left, otherwise returns the value in the -- Right. evalEitherM :: (MonadTest m, Show x, MonadCatch m, HasCallStack) => m (Either x a) -> m a -- | Fails the test if the ExceptT is Left, otherwise returns -- the value in the Right. evalExceptT :: (MonadTest m, Show x, HasCallStack) => ExceptT x m a -> m a -- | Fails the test if the Maybe is Nothing, otherwise -- returns the value in the Just. evalMaybe :: (MonadTest m, HasCallStack) => Maybe a -> m a -- | Fails the test if the action throws an exception, or if the -- Maybe is Nothing, otherwise returns the value in the -- Just. evalMaybeM :: (MonadTest m, MonadCatch m, HasCallStack) => m (Maybe a) -> m a -- | The name of a classifier. -- -- Should be constructed using OverloadedStrings: -- --
-- "apples" :: LabelName --data LabelName -- | Records the proportion of tests which satisfy a given condition. -- --
-- prop_with_classifier :: Property -- prop_with_classifier = -- property $ do -- xs <- forAll $ Gen.list (Range.linear 0 100) Gen.alpha -- for_ xs $ \x -> do -- classify "newborns" $ x == 0 -- classify "children" $ x > 0 && x < 13 -- classify "teens" $ x > 12 && x < 20 --classify :: (MonadTest m, HasCallStack) => LabelName -> Bool -> m () -- | Require a certain percentage of the tests to be covered by the -- classifier. -- --
-- prop_with_coverage :: Property -- prop_with_coverage = -- property $ do -- match <- forAll Gen.bool -- cover 30 "True" $ match -- cover 30 "False" $ not match ---- -- The example above requires a minimum of 30% coverage for both -- classifiers. If these requirements are not met, it will fail the test. cover :: (MonadTest m, HasCallStack) => CoverPercentage -> LabelName -> Bool -> m () -- | Add a label for each test run. It produces a table showing the -- percentage of test runs that produced each label. label :: (MonadTest m, HasCallStack) => LabelName -> m () -- | Like label, but uses Show to render its argument for -- display. collect :: (MonadTest m, Show a, HasCallStack) => a -> m () -- | The specification for the expected behaviour of an Action. -- These are used to generate sequences of actions to test. -- -- This is the main type you will use when writing state machine tests. -- gen is usually an instance of MonadGen, and m -- is usually an instance of MonadTest. These constraints appear -- when you pass your Command list to sequential or -- parallel. data Command (gen :: Type -> Type) (m :: Type -> Type) (state :: Type -> Type -> Type) Command :: (state Symbolic -> Maybe (gen (input Symbolic))) -> (input Concrete -> m output) -> [Callback input output state] -> Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -- | A generator which provides random arguments for a command. If the -- command cannot be executed in the current state, it should return -- Nothing. [commandGen] :: Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> state Symbolic -> Maybe (gen (input Symbolic)) -- | Executes a command using the arguments generated by commandGen. [commandExecute] :: Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> input Concrete -> m output -- | A set of callbacks which provide optional command configuration such -- as pre-condtions, post-conditions and state updates. [commandCallbacks] :: Command (gen :: Type -> Type) (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Callback input output state] -- | Optional command configuration. data Callback (input :: Type -> Type -> Type) output (state :: Type -> Type -> Type) -- | A pre-condition for a command that must be verified before the command -- can be executed. This is mainly used during shrinking to ensure that -- it is still OK to run a command despite the fact that some previously -- executed commands may have been removed from the sequence. Require :: (state Symbolic -> input Symbolic -> Bool) -> Callback (input :: (Type -> Type) -> Type) output (state :: (Type -> Type) -> Type) -- | Updates the model state, given the input and output of the command. -- Note that this function is polymorphic in the type of values. This is -- because it must work over Symbolic values when we are -- generating actions, and Concrete values when we are executing -- them. Update :: (forall (v :: Type -> Type). Ord1 v => state v -> input v -> Var output v -> state v) -> Callback (input :: (Type -> Type) -> Type) output (state :: (Type -> Type) -> Type) -- | A post-condition for a command that must be verified for the command -- to be considered a success. -- -- This callback receives the state prior to execution as the first -- argument, and the state after execution as the second argument. Ensure :: (state Concrete -> state Concrete -> input Concrete -> output -> Test ()) -> Callback (input :: (Type -> Type) -> Type) output (state :: (Type -> Type) -> Type) -- | An instantiation of a Command which can be executed, and its -- effect evaluated. data Action (m :: Type -> Type) (state :: Type -> Type -> Type) -- | A sequence of actions to execute. newtype Sequential (m :: Type -> Type) (state :: Type -> Type -> Type) Sequential :: [Action m state] -> Sequential (m :: Type -> Type) (state :: (Type -> Type) -> Type) -- | The sequence of actions. [sequentialActions] :: Sequential (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | A sequential prefix of actions to execute, with two branches to -- execute in parallel. data Parallel (m :: Type -> Type) (state :: Type -> Type -> Type) Parallel :: [Action m state] -> [Action m state] -> [Action m state] -> Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -- | The sequential prefix. [parallelPrefix] :: Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | The first branch. [parallelBranch1] :: Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | The second branch. [parallelBranch2] :: Parallel (m :: Type -> Type) (state :: (Type -> Type) -> Type) -> [Action m state] -- | Executes a list of actions sequentially, verifying that all -- post-conditions are met and no exceptions are thrown. -- -- To generate a sequence of actions to execute, see the -- sequential combinator in the Hedgehog.Gen module. executeSequential :: (MonadTest m, MonadCatch m, HasCallStack) => (forall (v :: Type -> Type). () => state v) -> Sequential m state -> m () -- | Executes the prefix actions sequentially, then executes the two -- branches in parallel, verifying that no exceptions are thrown and that -- there is at least one sequential interleaving where all the -- post-conditions are met. -- -- To generate parallel actions to execute, see the parallel -- combinator in the Hedgehog.Gen module. executeParallel :: (MonadTest m, MonadCatch m, MonadBaseControl IO m, HasCallStack) => (forall (v :: Type -> Type). () => state v) -> Parallel m state -> m () -- | Variables are the potential or actual result of executing an action. -- They are parameterised by either Symbolic or Concrete -- depending on the phase of the test. -- -- Symbolic variables are the potential results of actions. These -- are used when generating the sequence of actions to execute. They -- allow actions which occur later in the sequence to make use of the -- result of an action which came earlier in the sequence. -- -- Concrete variables are the actual results of actions. These are -- used during test execution. They provide access to the actual runtime -- value of a variable. -- -- The state update Callback for a command needs to be polymorphic -- in the type of variable because it is used in both the generation and -- the execution phase. -- -- The order of arguments makes Var FunctorB and -- TraversableB, which is how Symbolic values are turned -- into Concrete ones. newtype Var a (v :: Type -> Type) Var :: v a -> Var a (v :: Type -> Type) -- | Take the value from a concrete variable. concrete :: Var a Concrete -> a -- | Take the value from an opaque concrete variable. opaque :: Var (Opaque a) Concrete -> a -- | Symbolic values: Because hedgehog generates actions in a separate -- phase before execution, you will sometimes need to refer to the result -- of a previous action in a generator without knowing the value of the -- result (e.g., to get the ID of a previously-created user). -- -- Symbolic variables provide a token to stand in for the actual -- variables at generation time (and in Require/Update -- callbacks). At execution time, real values are available, so your -- execute actions work on Concrete variables. -- -- See also: Command, Var data Symbolic a -- | Concrete values: At test-execution time, Symbolic values from -- generation are replaced with Concrete values from performing -- actions. This type gives us something of the same kind as -- Symbolic to pass as a type argument to Var. newtype Concrete a [Concrete] :: forall a. a -> Concrete a -- | Opaque values. -- -- Useful if you want to put something without a Show instance -- inside something which you'd like to be able to display. -- -- For example: -- --
-- data State v =
-- State {
-- stateRefs :: [Var (Opaque (IORef Int)) v]
-- } deriving (Eq, Show)
--
newtype Opaque a
Opaque :: a -> Opaque a
[unOpaque] :: Opaque a -> a
-- | Distribute one monad transformer over another.
distributeT :: forall f (m :: Type -> Type) a. (MonadTransDistributive g, Transformer f g m) => g (f m) a -> f (g m) a
-- | Barbie-types that can be mapped over. Instances of FunctorB
-- should satisfy the following laws:
--
-- -- bmap id = id -- bmap f . bmap g = bmap (f . g) ---- -- There is a default bmap implementation for Generic -- types, so instances can derived automatically. class FunctorB (b :: k -> Type -> Type) bmap :: FunctorB b => (forall (a :: k). () => f a -> g a) -> b f -> b g ($dmbmap) :: forall f g. (FunctorB b, CanDeriveFunctorB b f g) => (forall (a :: k). () => f a -> g a) -> b f -> b g -- | Barbie-types that can be traversed from left to right. Instances -- should satisfy the following laws: -- --
-- t . btraverse f = btraverse (t . f) -- naturality -- btraverse Identity = Identity -- identity -- btraverse (Compose . fmap g . f) = Compose . fmap (btraverse g) . btraverse f -- composition ---- -- There is a default btraverse implementation for Generic -- types, so instances can derived automatically. class FunctorB b => TraversableB (b :: k -> Type -> Type) btraverse :: (TraversableB b, Applicative e) => (forall (a :: k). () => f a -> e (g a)) -> b f -> e (b g) ($dmbtraverse) :: forall e f g. (TraversableB b, Applicative e, CanDeriveTraversableB b f g) => (forall (a :: k). () => f a -> e (g a)) -> b f -> e (b g) newtype Rec p a (x :: k) Rec :: K1 R a x -> Rec p a (x :: k) [unRec] :: Rec p a (x :: k) -> K1 R a x -- | Lifting of the Eq class to unary type constructors. -- -- Any instance should be subject to the following law that canonicity is -- preserved: -- -- liftEq (==) = (==) -- -- This class therefore represents the generalization of Eq by -- decomposing its main method into a canonical lifting on a canonical -- inner method, so that the lifting can be reused for other arguments -- than the canonical one. class forall a. Eq a => Eq f a => Eq1 (f :: Type -> Type) -- | Lift the standard (==) function through the type -- constructor. eq1 :: (Eq1 f, Eq a) => f a -> f a -> Bool -- | Lifting of the Ord class to unary type constructors. -- -- Any instance should be subject to the following law that canonicity is -- preserved: -- -- liftCompare compare = compare -- -- This class therefore represents the generalization of Ord by -- decomposing its main method into a canonical lifting on a canonical -- inner method, so that the lifting can be reused for other arguments -- than the canonical one. class (Eq1 f, forall a. Ord a => Ord f a) => Ord1 (f :: Type -> Type) -- | Lift the standard compare function through the type -- constructor. compare1 :: (Ord1 f, Ord a) => f a -> f a -> Ordering -- | Lifting of the Show class to unary type constructors. -- -- Any instance should be subject to the following laws that canonicity -- is preserved: -- -- liftShowsPrec showsPrec showList = showsPrec -- -- liftShowList showsPrec showList = showList -- -- This class therefore represents the generalization of Show by -- decomposing it's methods into a canonical lifting on a canonical inner -- method, so that the lifting can be reused for other arguments than the -- canonical one. class forall a. Show a => Show f a => Show1 (f :: Type -> Type) -- | Lift the standard showsPrec and showList functions -- through the type constructor. showsPrec1 :: (Show1 f, Show a) => Int -> f a -> ShowS -- | Higher-order traversable functors. -- -- Deprecated in favor of TraversableB which can be derived -- using GHC.Generics -- | Deprecated: Replace with Hedgehog.TraversableB (defined in -- Data.Functor.Barbie) which can be derived automatically using -- GHC.Generics class HTraversable (t :: Type -> Type -> Type) htraverse :: (HTraversable t, Applicative f) => (forall a. () => g a -> f (h a)) -> t g -> f (t h)