| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Data.Validity
Contents
Description
Validity is used to specify additional invariants upon values that are not
enforced by the type system.
Let's take an example.
Suppose we were to implement a type Prime that represents prime integers.
If you were to completely enforce the invariant that the represented number is
a prime, then we could use Natural and only store the index of the
given prime in the infinite sequence of prime numbers.
This is very safe but also very expensive if we ever want to use the number,
because we would have to calculcate all the prime numbers until that index.
Instead we choose to implement Prime by a newtype Prime = Prime Int.
Now we have to maintain the invariant that the Int that we use to represent
the prime is in fact positive and a prime.
The Validity typeclass allows us to specify this invariant (and enables
testing via the genvalidity libraries:
https://hackage.haskell.org/package/genvalidity ):
instance Validity Prime where
validate (Prime n) = isPrime n <?@> "The 'Int' is prime."If certain typeclass invariants exist, you can make these explicit in the
validity instance as well.
For example, 'Fixed a' is only valid if a has an HasResolution instance,
so the correct validity instance is HasResolution a => Validity (Fixed a).
Synopsis
- class Validity a where
- trivialValidation :: a -> Validation
- genericValidate :: (Generic a, GValidity (Rep a)) => a -> Validation
- check :: Bool -> String -> Validation
- declare :: String -> Bool -> Validation
- annotate :: Validity a => a -> String -> Validation
- delve :: Validity a => String -> a -> Validation
- decorate :: String -> Validation -> Validation
- invalid :: String -> Validation
- valid :: Validation
- isValid :: Validity a => a -> Bool
- isInvalid :: Validity a => a -> Bool
- constructValid :: Validity a => a -> Maybe a
- constructValidUnsafe :: (Show a, Validity a) => a -> a
- newtype Validation = Validation {}
- data ValidationChain
- checkValidity :: Validity a => a -> Either [ValidationChain] a
- prettyValidation :: Validity a => a -> Either String a
- class Semigroup a => Monoid a where
- class Semigroup a where
Documentation
A class of types that have additional invariants defined upon them
Instances
| Validity Bool # | Trivially valid |
Defined in Data.Validity Methods validate :: Bool -> Validation # | |
| Validity Char # | Trivially valid |
Defined in Data.Validity Methods validate :: Char -> Validation # | |
| Validity Double # | NOT trivially valid:
|
Defined in Data.Validity Methods validate :: Double -> Validation # | |
| Validity Float # | NOT trivially valid:
|
Defined in Data.Validity Methods validate :: Float -> Validation # | |
| Validity Int # | Trivially valid |
Defined in Data.Validity Methods validate :: Int -> Validation # | |
| Validity Int8 # | Trivially valid |
Defined in Data.Validity Methods validate :: Int8 -> Validation # | |
| Validity Int16 # | Trivially valid |
Defined in Data.Validity Methods validate :: Int16 -> Validation # | |
| Validity Int32 # | Trivially valid |
Defined in Data.Validity Methods validate :: Int32 -> Validation # | |
| Validity Int64 # | Trivially valid |
Defined in Data.Validity Methods validate :: Int64 -> Validation # | |
| Validity Integer # | Trivially valid Integer is not trivially valid under the hood, but instantiating
|
Defined in Data.Validity Methods validate :: Integer -> Validation # | |
| Validity Natural # | Valid according to Only available with |
Defined in Data.Validity Methods validate :: Natural -> Validation # | |
| Validity Ordering # | Trivially valid |
Defined in Data.Validity Methods validate :: Ordering -> Validation # | |
| Validity Word # | Trivially valid |
Defined in Data.Validity Methods validate :: Word -> Validation # | |
| Validity Word8 # | Trivially valid |
Defined in Data.Validity Methods validate :: Word8 -> Validation # | |
| Validity Word16 # | Trivially valid |
Defined in Data.Validity Methods validate :: Word16 -> Validation # | |
| Validity Word32 # | Trivially valid |
Defined in Data.Validity Methods validate :: Word32 -> Validation # | |
| Validity Word64 # | Trivially valid |
Defined in Data.Validity Methods validate :: Word64 -> Validation # | |
| Validity () # | Trivially valid |
Defined in Data.Validity Methods validate :: () -> Validation # | |
| Validity ValidationChain # | |
Defined in Data.Validity Methods validate :: ValidationChain -> Validation # | |
| Validity a => Validity [a] # | 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 |
Defined in Data.Validity Methods validate :: [a] -> Validation # | |
| Validity a => Validity (Maybe a) # | A Maybe thing is valid if the thing inside is valid or it's nothing
It makes sense to assume that |
Defined in Data.Validity Methods validate :: Maybe a -> Validation # | |
| (Num a, Ord a, Validity a) => Validity (Ratio a) # | Valid if the contained numbers are valid and the denominator is strictly positive. |
Defined in Data.Validity Methods validate :: Ratio a -> Validation # | |
| HasResolution a => Validity (Fixed a) # | Valid according to the contained |
Defined in Data.Validity Methods validate :: Fixed a -> Validation # | |
| Validity a => Validity (NonEmpty a) # | A nonempty list is valid if all the elements are valid. See the instance for 'Validity [a]' for more information. |
Defined in Data.Validity Methods validate :: NonEmpty a -> Validation # | |
| (Validity a, Validity b) => Validity (Either a b) # | Any Either of things is valid if the contents are valid in either of the cases. |
Defined in Data.Validity Methods validate :: Either a b -> Validation # | |
| (Validity a, Validity b) => Validity (a, b) # | Any tuple of things is valid if both of its elements are valid |
Defined in Data.Validity Methods validate :: (a, b) -> Validation # | |
| (Validity a, Validity b, Validity c) => Validity (a, b, c) # | Any triple of things is valid if all three of its elements are valid |
Defined in Data.Validity Methods validate :: (a, b, c) -> Validation # | |
| (Validity a, Validity b, Validity c, Validity d) => Validity (a, b, c, d) # | Any quadruple of things is valid if all four of its elements are valid |
Defined in Data.Validity Methods validate :: (a, b, c, d) -> Validation # | |
| (Validity a, Validity b, Validity c, Validity d, Validity e) => Validity (a, b, c, d, e) # | Any quintuple of things is valid if all five of its elements are valid |
Defined in Data.Validity Methods validate :: (a, b, c, d, e) -> Validation # | |
| (Validity a, Validity b, Validity c, Validity d, Validity e, Validity f) => Validity (a, b, c, d, e, f) # | Any sextuple of things is valid if all six of its elements are valid |
Defined in Data.Validity Methods validate :: (a, b, c, d, e, f) -> Validation # | |
Helper functions to define validate
trivialValidation :: a -> Validation #
Declare any value to be valid in validation
trivialValidation a = seq a mempty
genericValidate :: (Generic a, GValidity (Rep a)) => a -> Validation #
check :: 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"
annotate :: 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"
]decorate :: String -> Validation -> Validation #
Decorate a validation with a location
invalid :: 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 -> validvalid :: Validation #
Utilities
Utilities for validity checking
constructValid :: Validity a => a -> Maybe a #
Construct a valid element from an unchecked element
constructValidUnsafe :: (Show a, Validity a) => a -> a #
Construct a valid element from an unchecked element, throwing error
on invalid elements.
Utilities for validation
newtype 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.
Constructors
| Validation | |
Fields | |
Instances
| Eq Validation # | |
Defined in Data.Validity | |
| Show Validation # | |
Defined in Data.Validity Methods showsPrec :: Int -> Validation -> ShowS # show :: Validation -> String # showList :: [Validation] -> ShowS # | |
| Generic Validation # | |
Defined in Data.Validity Associated Types type Rep Validation :: * -> * # | |
| Semigroup Validation # | |
Defined in Data.Validity Methods (<>) :: Validation -> Validation -> Validation # sconcat :: NonEmpty Validation -> Validation # stimes :: Integral b => b -> Validation -> Validation # | |
| Monoid Validation # | |
Defined in Data.Validity Methods mempty :: Validation # mappend :: Validation -> Validation -> Validation # mconcat :: [Validation] -> Validation # | |
| type Rep Validation # | |
Defined in Data.Validity type Rep Validation = D1 (MetaData "Validation" "Data.Validity" "validity-0.7.0.0-IAUu4Us1Nxz9hDCrt8ADs9" True) (C1 (MetaCons "Validation" PrefixI True) (S1 (MetaSel (Just "unValidation") NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 [ValidationChain]))) | |
data ValidationChain #
Constructors
| Violated String | |
| Location String ValidationChain |
Instances
checkValidity :: Validity a => a -> Either [ValidationChain] a #
validate a given value.
This function returns either all the reasons why the given value is invalid,
in the form of a list of ValidationChains, or it returns Right with the
input value, as evidence that it is valid.
Note: You map want to use prettyValidation instead, if you want to
display these ValidationChains to a user.
prettyValidation :: Validity a => a -> Either String a #
validate a given value, and return a nice error if the value is invalid.
Re-exports
class Semigroup a => Monoid a where #
The class of monoids (types with an associative binary operation that has an identity). Instances should satisfy the following laws:
x
<>mempty= xmempty<>x = xx(<>(y<>z) = (x<>y)<>zSemigrouplaw)mconcat=foldr'(<>)'mempty
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. Sum and Product.
NOTE: Semigroup is a superclass of Monoid since base-4.11.0.0.
Minimal complete definition
Methods
Identity of mappend
An associative operation
NOTE: This method is redundant and has the default
implementation since base-4.11.0.0.mappend = '(<>)'
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.
Instances
| Monoid Ordering | Since: base-2.1 |
| Monoid () | Since: base-2.1 |
| Monoid All | Since: base-2.1 |
| Monoid Any | Since: base-2.1 |
| Monoid Validation # | |
Defined in Data.Validity Methods mempty :: Validation # mappend :: Validation -> Validation -> Validation # mconcat :: [Validation] -> Validation # | |
| Monoid [a] | Since: base-2.1 |
| Semigroup a => Monoid (Maybe a) | Lift a semigroup into Since 4.11.0: constraint on inner Since: base-2.1 |
| Monoid a => Monoid (IO a) | Since: base-4.9.0.0 |
| Monoid a => Monoid (Identity a) | |
| Monoid (First a) | Since: base-2.1 |
| Monoid (Last a) | Since: base-2.1 |
| Monoid a => Monoid (Dual a) | Since: base-2.1 |
| Monoid (Endo a) | Since: base-2.1 |
| Num a => Monoid (Sum a) | Since: base-2.1 |
| Num a => Monoid (Product a) | Since: base-2.1 |
| Monoid b => Monoid (a -> b) | Since: base-2.1 |
| (Monoid a, Monoid b) => Monoid (a, b) | Since: base-2.1 |
| Monoid (Proxy s) | Since: base-4.7.0.0 |
| (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c) | Since: base-2.1 |
| Monoid a => Monoid (Const a b) | |
| Alternative f => Monoid (Alt f a) | Since: base-4.8.0.0 |
| (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (a, b, c, d) | Since: base-2.1 |
| (Monoid a, Monoid b, Monoid c, Monoid d, Monoid e) => Monoid (a, b, c, d, e) | Since: base-2.1 |
The class of semigroups (types with an associative binary operation).
Instances should satisfy the associativity law:
Since: base-4.9.0.0
Minimal complete definition
Instances
| Semigroup Ordering | Since: base-4.9.0.0 |
| Semigroup () | Since: base-4.9.0.0 |
| Semigroup All | Since: base-4.9.0.0 |
| Semigroup Any | Since: base-4.9.0.0 |
| Semigroup Validation # | |
Defined in Data.Validity Methods (<>) :: Validation -> Validation -> Validation # sconcat :: NonEmpty Validation -> Validation # stimes :: Integral b => b -> Validation -> Validation # | |
| Semigroup [a] | Since: base-4.9.0.0 |
| Semigroup a => Semigroup (Maybe a) | Since: base-4.9.0.0 |
| Semigroup a => Semigroup (IO a) | Since: base-4.10.0.0 |
| Semigroup a => Semigroup (Identity a) | |
| Semigroup (First a) | Since: base-4.9.0.0 |
| Semigroup (Last a) | Since: base-4.9.0.0 |
| Semigroup a => Semigroup (Dual a) | Since: base-4.9.0.0 |
| Semigroup (Endo a) | Since: base-4.9.0.0 |
| Num a => Semigroup (Sum a) | Since: base-4.9.0.0 |
| Num a => Semigroup (Product a) | Since: base-4.9.0.0 |
| Semigroup (NonEmpty a) | Since: base-4.9.0.0 |
| Semigroup b => Semigroup (a -> b) | Since: base-4.9.0.0 |
| Semigroup (Either a b) | Since: base-4.9.0.0 |
| (Semigroup a, Semigroup b) => Semigroup (a, b) | Since: base-4.9.0.0 |
| Semigroup (Proxy s) | Since: base-4.9.0.0 |
| (Semigroup a, Semigroup b, Semigroup c) => Semigroup (a, b, c) | Since: base-4.9.0.0 |
| Semigroup a => Semigroup (Const a b) | |
| Alternative f => Semigroup (Alt f a) | Since: base-4.9.0.0 |
| (Semigroup a, Semigroup b, Semigroup c, Semigroup d) => Semigroup (a, b, c, d) | Since: base-4.9.0.0 |
| (Semigroup a, Semigroup b, Semigroup c, Semigroup d, Semigroup e) => Semigroup (a, b, c, d, e) | Since: base-4.9.0.0 |