HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulegenvalidity-1.1.1.0Haskell2010

Data.GenValidity

GenValid exists to make tests involving Validity types easier and speed up the generation of data for them.

To implement tests for this datatype, we would have to be able to generate both primes. We could do this with a generator like this one:

(Prime <$> 'arbitrary') `suchThat` isValid

However, this is tedious and inefficient, as well as quite naive (because arbitrary tends to use very naive generators).

The GenValid type class allows you to specify how to (efficiently) generate valid data of the given type to allow for easier and quicker testing. The default implementation of GenValid already gives you a generator and shrinking function for free:

instance GenValid Prime

For example, to generate primes, we don't have to consider even numbers other than 2. A more efficient implementation could then look as follows:

instance GenValid Prime where
    genValid = Prime <$>
       (oneof
         [ pure 2
         , ((\y -> 2 * abs y + 1) <$> arbitrary) `suchThat` isPrime)
         ])

Typical examples of tests involving validity could look as follows:

it "succeeds when given valid input" $ do
    forAllValid $ \input ->
        myFunction input `shouldSatisfy` isRight
it "produces valid output when it succeeds" $ do
    forAllValid $ \input ->
        case myFunction input of
            Nothing -> return () -- Can happen
            Just output -> output `shouldSatisfy` isValid

Definitely also look at the companion packages for more info on how to use this package.

  • 2 types
  • 8 classes
  • 39 values
classclass Validity a => GenValid a where
#

A class of types for which valid values can be generated to be valid.

How to instantiate GenValid

Step 1: Try to instantiate GenValid without overriding any functions. It is possible that, if few values are valid or if validity checking is expensive, the resulting generator is too slow. In that case, go to Step 2.

Step 2: Consider using genValidStructurallyWithoutExtraChecking and shrinkValidStructurallyWithoutExtraFiltering to speed up generation. This only works if your type has a derived or trivial Validity instance.

Step 3: If that still is not fast enough, consider writing your own generator and shrinking function. Make sure to generate any possible valid value, but only valid values.

A note about Arbitrary

If you also write Arbitrary instances for GenValid types, it may be best to simply use

instance Arbitrary A where
  arbitrary = genValid
  shrink = shrinkValid

Methods

  • genValid :: Gen a

    Generate a valid datum, this should cover all possible valid values in the type

    The default implementation is as follows:

     genValid = genValidStructurally

    To speed up testing, it may be a good idea to implement this yourself. If you do, make sure that it is possible to generate all possible valid data, otherwise your testing may not cover all cases.

  • shrinkValid :: a -> [a]

    Shrink a valid value.

    The default implementation is as follows:

     shrinkValid = shrinkValidStructurally

    It is important that this shrinking function only shrinks values to valid values. If shrinkValid ever shrinks a value to an invalid value, the test that is being shrunk for might fail for a different reason than for the reason that it originally failed. This would lead to very confusing error messages.

Instances36GenValid, …

Helper functions

4 declarations

Generate a valid value by generating all the sub parts using the Generic instance,

This generator is _not_ guaranteed to generate a valid value.

This is probably _not_ the function that you are looking for when overriding genValid _unless_ the type in question has no _extra_ validity constraints on top of the validity of its sub parts.

Shrink a term to any of its immediate valid subterms, and also recursively shrink all subterms, and then filtering out the results that are not valid.

shrinkValidStructurally = filter isValid . shrinkValidStructurallyWithoutExtraFiltering

This is probably the function that you are looking for.

Helper functions for specific types

Char

String

Re-exports

35 declarations
classclass Validity a where
#

A class of types that have additional invariants defined upon them

Methods

Instances38Validity, …
  • Validity IntegerDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid

    Integer is not trivially valid under the hood, but instantiating Validity correctly would force validity to depend on a specific (big integer library integer-gmp versus integer-simple). This is rather impractical so for the time being we have opted for assuming that an Integer is always valid. Even though this is not technically sound, it is good enough for now.

  • Validity NaturalDefined in validity-0.12.1.0 · Data.Validity

    Valid according to isValidNatural

  • Validity Int16Defined in validity-0.12.1.0 · Data.Validity
  • Validity Int32Defined in validity-0.12.1.0 · Data.Validity
  • Validity Int64Defined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity Int8Defined in validity-0.12.1.0 · Data.Validity
  • Validity Word16Defined in validity-0.12.1.0 · Data.Validity
  • Validity Word32Defined in validity-0.12.1.0 · Data.Validity
  • Validity Word64Defined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity Word8Defined in validity-0.12.1.0 · Data.Validity
  • Validity BoolDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity CharDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity DoubleDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid:

  • Validity FloatDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid:

  • Validity IntDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity OrderingDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity WordDefined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity ValidationChainDefined in validity-0.12.1.0 · Data.Validity
  • Validity ()Defined in validity-0.12.1.0 · Data.Validity

    Trivially valid

  • Validity a => Validity (First a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (Last a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (NonEmpty a)Defined in validity-0.12.1.0 · Data.Validity

    A nonempty list is valid if all the elements are valid.

    See the instance for 'Validity [a]' for more information.

  • Validity a => Validity (Identity a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (First a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (Last a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (Dual a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (Maybe a)Defined in validity-0.12.1.0 · Data.Validity

    A Maybe thing is valid if the thing inside is valid or it's nothing It makes sense to assume that Nothing is valid. If Nothing wasn't valid, you wouldn't have used a Maybe in the datastructure.

  • Validity a => Validity [a]Defined in validity-0.12.1.0 · Data.Validity

    A list of things is valid if all of the things are valid.

    This means that the empty list is considered valid. If the empty list should not be considered valid as part of your custom data type, make sure to write a custom Validity instance

  • (Validity a, Ord a, Num a, Integral a) => Validity (Ratio a)Defined in validity-0.12.1.0 · Data.Validity

    Valid if the contained numbers are valid and the denominator is strictly positive.

  • HasResolution a => Validity (Fixed a)Defined in validity-0.12.1.0 · Data.Validity

    Valid according to the contained Integer.

  • (Validity a, Validity b) => Validity (Either a b)Defined in validity-0.12.1.0 · Data.Validity

    Any Either of things is valid if the contents are valid in either of the cases.

  • (Validity a, Validity b) => Validity (a, b)Defined in validity-0.12.1.0 · Data.Validity

    Any tuple of things is valid if both of its elements are valid

  • Validity (f a) => Validity (Alt f a)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • Validity a => Validity (Const a b)Defined in validity-0.12.1.0 · Data.Validity

    Valid values the same as it's base type:

  • (Validity a, Validity b, Validity c) => Validity (a, b, c)Defined in validity-0.12.1.0 · Data.Validity

    Any triple of things is valid if all three of its elements are valid

  • (Validity a, Validity b, Validity c, Validity d) => Validity (a, b, c, d)Defined in validity-0.12.1.0 · Data.Validity

    Any quadruple of things is valid if all four of its elements are valid

  • (Validity a, Validity b, Validity c, Validity d, Validity e) => Validity (a, b, c, d, e)Defined in validity-0.12.1.0 · Data.Validity

    Any quintuple of things is valid if all five of its elements are valid

  • (Validity a, Validity b, Validity c, Validity d, Validity e, Validity f) => Validity (a, b, c, d, e, f)Defined in validity-0.12.1.0 · Data.Validity

    Any sextuple of things is valid if all six of its elements are valid

classclass Semigroup a => Monoid a where
#

The class of monoids (types with an associative binary operation that has an identity). Instances should satisfy the following:

Right identity

x <> mempty = x

Left identity

mempty <> x = x

Associativity

x <> (y <> z) = (x <> y) <> z

(

Semigroup

law)

Concatenation

mconcat = foldr (<>) mempty

You can alternatively define mconcat instead of mempty, in which case the laws are:

Unit

mconcat (pure x) = x

Multiplication

mconcat (join xss) = mconcat (fmap mconcat xss)

Subclass

mconcat (toList xs) = sconcat xs

The method names refer to the monoid of lists under concatenation, but there are many other instances.

Some types can be viewed as a monoid in more than one way, e.g. both addition and multiplication on numbers. In such cases we often define newtypes and make those instances of Monoid, e.g. Data.Semigroup.Sum and Data.Semigroup.Product.

NOTE: Semigroup is a superclass of Monoid since base-4.11.0.0.

Methods

  • mempty :: a

    Identity of mappend

    Examples
    Example1 expression
    "Hello world" <> mempty"Hello world"
    Example1 expression
    mempty <> [1, 2, 3][1,2,3]
  • mappend :: a -> 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.

  • mconcat :: [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.

    Example1 expression
    mconcat ["Hello", " ", "Haskell", "!"]"Hello Haskell!"
Instances70Monoid, …
  • Monoid ByteArrayDefined in base-4.20.2.0 · Data.Array.Byte
  • Monoid BuilderDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
  • Monoid ByteStringDefined in bytestring-0.12.2.0 · Data.ByteString.Internal.Type
  • Monoid ByteStringDefined in bytestring-0.12.2.0 · Data.ByteString.Lazy.Internal
  • Monoid ShortByteStringDefined in bytestring-0.12.2.0 · Data.ByteString.Short.Internal
  • Monoid IntSetDefined in containers-0.7 · Data.IntSet.Internal
  • Monoid AllDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Monoid AnyDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Monoid EventDefined in ghc-internal-9.1003.0 · GHC.Internal.Event.Internal.Types
  • Monoid EventLifetimeDefined in ghc-internal-9.1003.0 · GHC.Internal.Event.Internal.Types
  • Monoid LifetimeDefined in ghc-internal-9.1003.0 · GHC.Internal.Event.Internal.Types

    mappend takes the longer of two lifetimes.

  • Monoid ExceptionContextDefined in ghc-internal-9.1003.0 · GHC.Internal.Exception.Context
  • Monoid OrderingDefined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid DocDefined in pretty-1.1.3.6 · Text.PrettyPrint.HughesPJ
  • Monoid ValidationDefined in validity-0.12.1.0 · Data.Validity
  • Monoid ()Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid (Comparison a)Defined in base-4.20.2.0 · Data.Functor.Contravariant

    mempty on comparisons always returns EQ. Without newtypes this equals pure (pure EQ).

    mempty :: Comparison a
    mempty = Comparison _ _ -> EQ
    
  • Monoid (Equivalence a)Defined in base-4.20.2.0 · Data.Functor.Contravariant

    mempty on equivalences always returns True. Without newtypes this equals pure (pure True).

    mempty :: Equivalence a
    mempty = Equivalence _ _ -> True
    
  • Monoid (Predicate a)Defined in base-4.20.2.0 · Data.Functor.Contravariant

    mempty on predicates always returns True. Without newtypes this equals pure True.

    mempty :: Predicate a
    mempty = _ -> True
    
  • Monoid (IntMap a)Defined in containers-0.7 · Data.IntMap.Internal
  • Monoid (Seq a)Defined in containers-0.7 · Data.Sequence.Internal
  • Monoid (MergeSet a)Defined in containers-0.7 · Data.Set.Internal
  • Monoid (First a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Monoid
  • Monoid (Last a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Monoid
  • Monoid (Endo a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Monoid (Doc a)Defined in pretty-1.1.3.6 · Text.PrettyPrint.Annotated.HughesPJ
  • Monoid [a]Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid a => Monoid (STM a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Conc.Sync
  • Monoid a => Monoid (Identity a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Functor.Identity
  • Monoid a => Monoid (Down a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Ord
  • Monoid a => Monoid (Dual a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Monoid a => Monoid (IO a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid a => Monoid (Q a)Defined in template-haskell-2.22.0.0 · Language.Haskell.TH.Syntax
  • Monoid a => Monoid (a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid m => Monoid (WrappedMonoid m)Defined in base-4.20.2.0 · Data.Semigroup
  • Monoid p => Monoid (Par1 p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • Semigroup a => Monoid (Maybe a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base

    Lift a semigroup into Maybe forming a Monoid according to http://en.wikipedia.org/wiki/Monoid: "Any semigroup S may be turned into a monoid simply by adjoining an element e not in S and defining e*e = e and e*s = s = s*e for all s ∈ S."

    Since 4.11.0: constraint on inner a value generalised from Monoid to Semigroup.

  • Bits a => Monoid (Ior a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Bits
  • Bits a => Monoid (Xor a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Bits
  • FiniteBits a => Monoid (And a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Bits

    This constraint is arguably too strong. However, as some types (such as Natural) have undefined complement, this is the only safe choice.

  • FiniteBits a => Monoid (Iff a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Bits

    This constraint is arguably too strong. However, as some types (such as Natural) have undefined complement, this is the only safe choice.

  • Num a => Monoid (Product a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Num a => Monoid (Sum a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Ord a => Monoid (Set a)Defined in containers-0.7 · Data.Set.Internal
  • Ord a => Monoid (Max a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Functor.Utils
  • Ord a => Monoid (Min a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Functor.Utils
  • (Generic a, Monoid (Rep a ())) => Monoid (Generically a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • (Ord a, Bounded a) => Monoid (Max a)Defined in base-4.20.2.0 · Data.Semigroup
  • (Ord a, Bounded a) => Monoid (Min a)Defined in base-4.20.2.0 · Data.Semigroup
  • Monoid (Proxy s)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Proxy
  • Monoid (U1 p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • Monoid a => Monoid (Op a b)Defined in base-4.20.2.0 · Data.Functor.Contravariant

    mempty @(Op a b) without newtypes is mempty @(b->a) = _ -> mempty.

    mempty :: Op a b
    mempty = Op _ -> mempty
    
  • Monoid a => Monoid (ST s a)Defined in ghc-internal-9.1003.0 · GHC.Internal.ST
  • Monoid b => Monoid (a -> b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Ord k => Monoid (Map k v)Defined in containers-0.7 · Data.Map.Internal
  • (Monoid a, Monoid b) => Monoid (a, b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Alternative f => Monoid (Alt f a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Semigroup.Internal
  • Monoid (f p) => Monoid (Rec1 f p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • Monoid a => Monoid (Const a b)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Functor.Const
  • Monoid a => Monoid (Constant a b)Defined in transformers-0.6.1.1 · Data.Functor.Constant
  • (Applicative f, Monoid a) => Monoid (Ap f a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Monoid
  • (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid c => Monoid (K1 i c p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • (Monoid (f a), Monoid (g a)) => Monoid (Product f g a)Defined in base-4.20.2.0 · Data.Functor.Product
  • (Monoid (f p), Monoid (g p)) => Monoid ((:*:) f g p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a, b, c, d)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
  • Monoid (f (g a)) => Monoid (Compose f g a)Defined in base-4.20.2.0 · Data.Functor.Compose
  • Monoid (f (g p)) => Monoid ((:.:) f g p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • Monoid (f p) => Monoid (M1 i c f p)Defined in ghc-internal-9.1003.0 · GHC.Internal.Generics
  • (Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) => Monoid (a, b, c, d, e)Defined in ghc-internal-9.1003.0 · GHC.Internal.Base
classclass Semigroup a where
#

The class of semigroups (types with an associative binary operation).

Instances should satisfy the following:

Associativity

x <> (y <> z) = (x <> y) <> z

You can alternatively define sconcat instead of (<>), in which case the laws are:

Unit

sconcat (pure x) = x

Multiplication

sconcat (join xss) = sconcat (fmap sconcat xss)

Methods

  • (<>) :: a -> a -> ainfixr 6

    An associative operation.

    Examples
    Example1 expression
    [1,2,3] <> [4,5,6][1,2,3,4,5,6]
    Example1 expression
    Just [1, 2, 3] <> Just [4, 5, 6]Just [1,2,3,4,5,6]
    Example1 expression
    putStr "Hello, " <> putStrLn "World!"Hello, World!
  • sconcat :: NonEmpty a -> a

    Reduce a non-empty list with <>

    The default definition should be sufficient, but this can be overridden for efficiency.

    Examples

    For the following examples, we will assume that we have:

    Example1 expression
    import Data.List.NonEmpty (NonEmpty (..))
    Example1 expression
    sconcat $ "Hello" :| [" ", "Haskell", "!"]"Hello Haskell!"
    Example1 expression
    sconcat $ Just [1, 2, 3] :| [Nothing, Just [4, 5, 6]]Just [1,2,3,4,5,6]
    Example1 expression
    sconcat $ Left 1 :| [Right 2, Left 3, Right 4]Right 2
  • stimes :: Integral b => b -> 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 \mathcal{O}(1) by picking stimes = stimesIdempotent or stimes = stimesIdempotentMonoid respectively.

    Examples
    Example1 expression
    stimes 4 [1][1,1,1,1]
    Example1 expression
    stimes 5 (putStr "hi!")hi!hi!hi!hi!hi!
    Example1 expression
    stimes 3 (Right ":)")Right ":)"
Instances80Semigroup, …
datadata ValidationChain
#
Instances5Eq, Show, Generic, Validity, Rep
newtypenewtype Validation
#

The result of validating a value.

mempty means the value was valid.

This type intentionally doesn't have a Validity instance to make sure you can never accidentally use annotate or delve twice.

Instances6Eq, Show, Generic, Semigroup, Monoid, Rep
valueannotate :: Validity a => a -> String -> Validation
#

Declare a sub-part as a necessary part for validation, and annotate it with a name.

Example:

validate (a, b) =
    mconcat
        [ annotate a "The first element of the tuple"
        , annotate b "The second element of the tuple"
        ]
valuecheck :: Bool -> String -> Validation
#

Check that a given invariant holds.

The given string should describe the invariant, not the violation.

Example:

check (x < 5) "x is strictly smaller than 5"

instead of

check (x < 5) "x is greater than 5"
valueinvalid :: String -> Validation
#

Construct a trivially invalid Validation

Example:

data Wrong
    = Wrong
    | Fine
    deriving (Show, Eq)

instance Validity Wrong where
    validate w =
        case w of
            Wrong -> invalid "Wrong"
            Fine -> valid
valueprettyValidate :: Validity a => a -> Either String a
#

Validate a given value

This function will return a nice error if the value is invalid. It will return the original value in Right if it was valid, as evidence that it has been validated.

The Generics magic

5 declarations
classclass GGenValid (f :: Type -> Type) where
#

Methods

Instances5GGenValid
classclass GValidRecursivelyShrink (f :: Type -> Type) where
#

Methods

Instances6GValidRecursivelyShrink
classclass GValidSubterms (f :: Type -> Type) a where
#

Methods

Instances6GValidSubterms
classclass GValidSubtermsIncl (f :: Type -> Type) a where
#

Methods

Instances7GValidSubtermsIncl, …