-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Validity typeclass -- -- For more info, see the readme. -- -- Note: There are companion instance packages for this library: -- -- @package validity @version 0.4.0.2 -- | 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."
--       isValid (Prime n) = isPrime n
--   
-- -- 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). module Data.Validity -- | A class of types that have additional invariants defined upon them -- that aren't enforced by the type system -- --

Purpose

-- -- validate checks whether a given value is a valid value and -- reports all reasons why the given value is not valid if that is the -- case. -- -- isValid only checks whether a given value is a valid value of -- its type. -- --

Instantiating Validity

-- -- To instantiate Validity, one has to implement both -- isValid and validate. Start by implementing -- validate. Use the helper functions below to define all the -- reasons why a given value would be a valid value of its type. Then -- define `isValid = isValidbyValidating' for now. -- -- Example: -- --
--   newtype Even = Even Int
--   
--   instance Validity Even
--       validate (Event i)
--         even i <?@> "The contained 'Int' is even."
--       isValid = isValidByValidating
--   
-- -- If it turns out that, at this point, isValid is too slow for -- your taste, you can replace the implementation of isValid by a -- custom implementation. However, it is important that this -- isValid implementation has exactly the same semantics as -- isValidbyValidating. -- -- Example: -- --
--   newtype Even = Even Int
--   
--   instance Validity Even
--       validate (Event i)
--         even i <?@> "The contained 'Int' is even."
--       isValid (Event i) = even i
--   
-- --

Semantics

-- -- isValid should be an underapproximation of actual validity. -- -- This means that if isValid is not a perfect representation of -- actual validity, for safety reasons, it should never return -- True for invalid values, but it may return False for -- valid values. -- -- For example: -- --
--   isValid = const False
--   
-- -- is a valid implementation for any type, because it never returns -- True for invalid values. -- --
--   isValid (Even i) = i == 2
--   
-- -- is a valid implementation for newtype Even = Even Int, but -- --
--   isValid (Even i) = even i || i == 1
--   
-- -- is not because it returns True for an invalid value: '1'. -- --

Automatic instances with Generic

-- -- An instance of this class can be made automatically if the type in -- question has a Generic instance. This instance will try to use -- isValid to on all structural sub-parts of the value that is -- being checked for validity. -- -- Example: -- --
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   data MyType = MyType
--       { myDouble :: Double
--       { myString :: String
--       } deriving (Show, Eq, Generic)
--   
--   instance Validity MyType
--   
-- -- generates something like: -- --
--   instance Validity MyType where
--       isValid (MyType d s)
--           = isValid d && isValid s
--       validate (MyType d s)
--           = d <?!> "myDouble"
--          <> s <?!> "myString"
--   
class Validity a where validate = gValidate . from isValid = gIsValid . from validate :: Validity a => a -> Validation validate :: (Validity a, Generic a, GValidity (Rep a)) => a -> Validation isValid :: Validity a => a -> Bool isValid :: (Validity a, Generic a, GValidity (Rep a)) => a -> Bool -- | Declare any value to be valid. -- --
--   triviallyValid a = seq a True
--   
triviallyValid :: a -> Bool -- | Declare any value to be valid in validation -- --
--   trivialValidation a = seq a mempty
--   
trivialValidation :: a -> Validation -- | Implement isValid by using validate and checking that -- there are no reasons that the value is invalid. isValidByValidating :: Validity a => a -> Bool -- | 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"
--   
check :: Bool -> String -> Validation -- | Infix operator for annotate -- -- Example: -- --
--   validate (a, b) =
--       mconcat
--           [ a <?!> "The first element of the tuple"
--           , b <?!> "The second element of the tuple"
--           ]
--   
() :: Validity a => a -> String -> Validation infixr 0 -- | 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"
--           ]
--   
annotate :: Validity a => a -> String -> Validation -- | Infix operator for check -- -- Example: -- --
--   x < 5 <?@> "x is strictly smaller than 5"
--   
() :: Bool -> String -> Validation infixr 0 -- | Implement validate by using isValid and using the given -- string as the reason if the value is invalid. validateByChecking :: Validity a => String -> a -> Validation -- | Implement validate by using isValid and using the given -- name to define the reason if the value is invalid. -- --
--   validateByCheckingName name = validateByChecking $ unwords ["The", name, "valid."]
--   
validateByCheckingName :: Validity a => String -> a -> Validation -- | Implement validate by using isValid and using a default -- reason if the value is invalid. -- --
--   validateByCheckingDefault = validateByChecking "The value is valid."
--   
validateByCheckingDefault :: Validity a => a -> Validation -- | Check whether isInvalid is not valid. -- --
--   isInvalid = not . isValid
--   
isInvalid :: Validity a => a -> Bool -- | Construct a valid element from an unchecked element constructValid :: Validity a => a -> Maybe a -- | Construct a valid element from an unchecked element, throwing -- error on invalid elements. constructValidUnsafe :: (Show a, Validity a) => a -> a newtype Validation Validation :: [ValidationChain] -> Validation [unValidation] :: Validation -> [ValidationChain] data ValidationChain Violated :: String -> ValidationChain Location :: String -> ValidationChain -> ValidationChain -- | 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. checkValidity :: Validity a => a -> Either [ValidationChain] a -- | validate a given value, and return a nice error if the value is -- invalid. prettyValidation :: Validity a => a -> Either String a -- | The class of monoids (types with an associative binary operation that -- has an identity). Instances should satisfy the following laws: -- -- -- -- 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. class Monoid a -- | Identity of mappend mempty :: Monoid a => a -- | An associative operation 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 :: Monoid a => [a] -> a instance GHC.Generics.Generic Data.Validity.Validation instance GHC.Classes.Eq Data.Validity.Validation instance GHC.Show.Show Data.Validity.Validation instance GHC.Generics.Generic Data.Validity.ValidationChain instance GHC.Classes.Eq Data.Validity.ValidationChain instance GHC.Show.Show Data.Validity.ValidationChain instance Data.Validity.Validity Data.Validity.ValidationChain instance Data.Validity.Validity Data.Validity.Validation instance GHC.Base.Monoid Data.Validity.Validation instance (Data.Validity.Validity a, Data.Validity.Validity b) => Data.Validity.Validity (a, b) instance (Data.Validity.Validity a, Data.Validity.Validity b) => Data.Validity.Validity (Data.Either.Either a b) instance (Data.Validity.Validity a, Data.Validity.Validity b, Data.Validity.Validity c) => Data.Validity.Validity (a, b, c) instance (Data.Validity.Validity a, Data.Validity.Validity b, Data.Validity.Validity c, Data.Validity.Validity d) => Data.Validity.Validity (a, b, c, d) instance (Data.Validity.Validity a, Data.Validity.Validity b, Data.Validity.Validity c, Data.Validity.Validity d, Data.Validity.Validity e) => Data.Validity.Validity (a, b, c, d, e) instance (Data.Validity.Validity a, Data.Validity.Validity b, Data.Validity.Validity c, Data.Validity.Validity d, Data.Validity.Validity e, Data.Validity.Validity f) => Data.Validity.Validity (a, b, c, d, e, f) instance Data.Validity.Validity a => Data.Validity.Validity [a] instance Data.Validity.Validity a => Data.Validity.Validity (Data.List.NonEmpty.NonEmpty a) instance Data.Validity.Validity a => Data.Validity.Validity (GHC.Base.Maybe a) instance Data.Validity.Validity () instance Data.Validity.Validity GHC.Types.Bool instance Data.Validity.Validity GHC.Types.Ordering instance Data.Validity.Validity GHC.Types.Char instance Data.Validity.Validity GHC.Types.Int instance Data.Validity.Validity GHC.Types.Word instance Data.Validity.Validity GHC.Word.Word8 instance Data.Validity.Validity GHC.Word.Word16 instance Data.Validity.Validity GHC.Word.Word32 instance Data.Validity.Validity GHC.Word.Word64 instance Data.Validity.Validity GHC.Types.Float instance Data.Validity.Validity GHC.Types.Double instance Data.Validity.Validity GHC.Integer.Type.Integer instance Data.Validity.Validity GHC.Natural.Natural instance Data.Validity.Validity GHC.Real.Rational instance Data.Fixed.HasResolution a => Data.Validity.Validity (Data.Fixed.Fixed a) instance Data.Validity.GValidity GHC.Generics.U1 instance Data.Validity.GValidity GHC.Generics.V1 instance (Data.Validity.GValidity a, Data.Validity.GValidity b) => Data.Validity.GValidity (a GHC.Generics.:*: b) instance (Data.Validity.GValidity a, Data.Validity.GValidity b) => Data.Validity.GValidity (a GHC.Generics.:+: b) instance (Data.Validity.GValidity a, GHC.Generics.Datatype c) => Data.Validity.GValidity (GHC.Generics.M1 GHC.Generics.D c a) instance (Data.Validity.GValidity a, GHC.Generics.Constructor c) => Data.Validity.GValidity (GHC.Generics.M1 GHC.Generics.C c a) instance (Data.Validity.GValidity a, GHC.Generics.Selector c) => Data.Validity.GValidity (GHC.Generics.M1 GHC.Generics.S c a) instance Data.Validity.Validity a => Data.Validity.GValidity (GHC.Generics.K1 GHC.Generics.R a) -- | Relative validity module Data.RelativeValidity -- | A class of types that have additional invariants defined upon them -- that aren't enforced by the type system -- -- If there is a Validity a instance as well, then a -- isValidFor b should imply isValid a for any -- b. -- -- If there is a Validity b instance as well, then a -- isValidFor b should imply isValid b for any -- a. class RelativeValidity a b isValidFor :: RelativeValidity a b => a -> b -> Bool isInvalidFor :: RelativeValidity a b => a -> b -> Bool