| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Refined
Contents
Description
In type theory, a refinement type is a type endowed with a predicate which is assumed to hold for any element of the refined type.
This library allows one to capture the idea of a refinement type
using the Refined type. A Refined p x wraps a value
of type x, ensuring that it satisfies a type-level predicate p.
A simple introduction to this library can be found here: http://nikita-volkov.github.io/refined/
This module only provides safe constructions of Refined
values, safe meaning that the refinement predicate holds,
and the construction of the Refined value is total.
If you can manually prove that the refinement predicate holds, or you do not necessarily care about this definition of safety, use the module Refined.Unsafe.
Synopsis
- data Refined p x
- refine :: Predicate p x => x -> Either RefineException (Refined p x)
- refineThrow :: (Predicate p x, MonadThrow m) => x -> m (Refined p x)
- refineFail :: (Predicate p x, MonadFail m) => x -> m (Refined p x)
- refineError :: (Predicate p x, MonadError RefineException m) => x -> m (Refined p x)
- refineTH :: (Predicate p x, Lift x) => x -> Q (TExp (Refined p x))
- unrefine :: Refined p x -> x
- class Typeable p => Predicate p x where
- data Not p
- data And l r
- type (&&) = And
- data Or l r
- type (||) = Or
- data IdPred
- data LessThan (n :: Nat)
- data GreaterThan (n :: Nat)
- data From (n :: Nat)
- data To (n :: Nat)
- data FromTo (mn :: Nat) (mx :: Nat)
- data EqualTo (n :: Nat)
- data NotEqualTo (n :: Nat)
- type Positive = GreaterThan 0
- type NonPositive = To 0
- type Negative = LessThan 0
- type NonNegative = From 0
- type ZeroToOne = FromTo 0 1
- type NonZero = NotEqualTo 0
- data SizeLessThan (n :: Nat)
- data SizeGreaterThan (n :: Nat)
- data SizeEqualTo (n :: Nat)
- type NonEmpty = SizeGreaterThan 0
- data Ascending
- data Descending
- class Weaken from to where
- andLeft :: Refined (And l r) x -> Refined l x
- andRight :: Refined (And l r) x -> Refined r x
- leftOr :: Refined l x -> Refined (Or l r) x
- rightOr :: Refined r x -> Refined (Or l r) x
- data RefineException
- displayRefineException :: RefineException -> Doc ann
- data RefineT m a
- runRefineT :: RefineT m a -> m (Either RefineException a)
- mapRefineT :: (m (Either RefineException a) -> n (Either RefineException b)) -> RefineT m a -> RefineT n b
- type RefineM a = RefineT Identity a
- refineM :: Either RefineException a -> RefineM a
- runRefineM :: RefineM a -> Either RefineException a
- throwRefine :: Monad m => RefineException -> RefineT m a
- catchRefine :: Monad m => RefineT m a -> (RefineException -> RefineT m a) -> RefineT m a
- throwRefineOtherException :: Monad m => TypeRep -> Doc Void -> RefineT m a
- pretty :: Pretty a => a -> Doc ann
Refined
A refinement type, which wraps a value of type x,
ensuring that it satisfies a type-level predicate p.
Instances
| Foldable (Refined p) Source # | |
Defined in Refined.Internal Methods fold :: Monoid m => Refined p m -> m # foldMap :: Monoid m => (a -> m) -> Refined p a -> m # foldr :: (a -> b -> b) -> b -> Refined p a -> b # foldr' :: (a -> b -> b) -> b -> Refined p a -> b # foldl :: (b -> a -> b) -> b -> Refined p a -> b # foldl' :: (b -> a -> b) -> b -> Refined p a -> b # foldr1 :: (a -> a -> a) -> Refined p a -> a # foldl1 :: (a -> a -> a) -> Refined p a -> a # toList :: Refined p a -> [a] # length :: Refined p a -> Int # elem :: Eq a => a -> Refined p a -> Bool # maximum :: Ord a => Refined p a -> a # minimum :: Ord a => Refined p a -> a # | |
| Eq x => Eq (Refined p x) Source # | |
| Ord x => Ord (Refined p x) Source # | |
Defined in Refined.Internal | |
| (Read x, Predicate p x) => Read (Refined p x) Source # | This instance makes sure to check the refinement. |
| Show x => Show (Refined p x) Source # | |
| Lift x => Lift (Refined p x) Source # | |
| (Arbitrary a, Predicate p a) => Arbitrary (Refined p a) Source # | |
| (ToJSON a, Predicate p a) => ToJSON (Refined p a) Source # | |
Defined in Refined.Orphan.Aeson | |
| (FromJSON a, Predicate p a) => FromJSON (Refined p a) Source # | |
Creation
refine :: Predicate p x => x -> Either RefineException (Refined p x) Source #
A smart constructor of a Refined value.
Checks the input value at runtime.
refineThrow :: (Predicate p x, MonadThrow m) => x -> m (Refined p x) Source #
refineError :: (Predicate p x, MonadError RefineException m) => x -> m (Refined p x) Source #
Constructs a Refined value at run-time,
calling throwError if the value
does not satisfy the predicate.
refineTH :: (Predicate p x, Lift x) => x -> Q (TExp (Refined p x)) Source #
Constructs a Refined value at compile-time using -XTemplateHaskell.
For example:
>>>$$(refineTH 23) :: Refined Positive IntRefined 23
Here's an example of an invalid value:
>>>$$(refineTH 0) :: Refined Positive Int<interactive>:6:4: Value is not greater than 0 In the Template Haskell splice $$(refineTH 0) In the expression: $$(refineTH 0) :: Refined Positive Int In an equation for ‘it’: it = $$(refineTH 0) :: Refined Positive Int
If it's not evident, the example above indicates a compile-time failure, which means that the checking was done at compile-time, thus introducing a zero runtime overhead compared to a plain value construction.
It may be useful to use this function with the `th-lift-instances` package at https://hackage.haskell.org/package/th-lift-instances/
Consumption
Predicate
class Typeable p => Predicate p x where Source #
A typeclass which defines a runtime interpretation of
a type-level predicate p for type x.
Methods
validate :: Monad m => p -> x -> RefineT m () Source #
Check the value x according to the predicate p,
producing an error string if the value does not satisfy.
Instances
Logical predicates
The negation of a predicate.
The conjunction of two predicates.
The disjunction of two predicates.
Identity predicate
A predicate which is satisfied for all types.
Numeric predicates
data LessThan (n :: Nat) Source #
A Predicate ensuring that the value is less than the
specified type-level number.
data GreaterThan (n :: Nat) Source #
A Predicate ensuring that the value is greater than the
specified type-level number.
Instances
| Generic (GreaterThan n) Source # | |
Defined in Refined.Internal Associated Types type Rep (GreaterThan n) :: Type -> Type # Methods from :: GreaterThan n -> Rep (GreaterThan n) x # to :: Rep (GreaterThan n) x -> GreaterThan n # | |
| (Ord x, Num x, KnownNat n) => Predicate (GreaterThan n) x Source # | |
Defined in Refined.Internal | |
| m <= n => Weaken (GreaterThan n) (From m) Source # | |
Defined in Refined.Internal | |
| m <= n => Weaken (GreaterThan n) (GreaterThan m) Source # | |
Defined in Refined.Internal Methods weaken :: Refined (GreaterThan n) x -> Refined (GreaterThan m) x Source # | |
| type Rep (GreaterThan n) Source # | |
Defined in Refined.Internal | |
A Predicate ensuring that the value is greater than or equal to the
specified type-level number.
A Predicate ensuring that the value is less than or equal to the
specified type-level number.
data FromTo (mn :: Nat) (mx :: Nat) Source #
A Predicate ensuring that the value is within an inclusive range.
Instances
| Generic (FromTo mn mx) Source # | |
| (Ord x, Num x, KnownNat mn, KnownNat mx, mn <= mx) => Predicate (FromTo mn mx) x Source # | |
| m <= q => Weaken (FromTo n m) (To q) Source # | |
| p <= n => Weaken (FromTo n m) (From p) Source # | |
| (p <= n, m <= q) => Weaken (FromTo n m) (FromTo p q) Source # | |
| type Rep (FromTo mn mx) Source # | |
data EqualTo (n :: Nat) Source #
A Predicate ensuring that the value is equal to the specified
type-level number n.
data NotEqualTo (n :: Nat) Source #
A Predicate ensuring that the value is not equal to the specified
type-level number n.
Instances
| Generic (NotEqualTo n) Source # | |
Defined in Refined.Internal Associated Types type Rep (NotEqualTo n) :: Type -> Type # | |
| (Eq x, Num x, KnownNat n) => Predicate (NotEqualTo n) x Source # | |
Defined in Refined.Internal | |
| type Rep (NotEqualTo n) Source # | |
Defined in Refined.Internal | |
type Positive = GreaterThan 0 Source #
A Predicate ensuring that the value is greater than zero.
type NonPositive = To 0 Source #
A Predicate ensuring that the value is less than or equal to zero.
type NonNegative = From 0 Source #
A Predicate ensuring that the value is greater than or equal to zero.
type NonZero = NotEqualTo 0 Source #
A Predicate ensuring that the value is not equal to zero.
Foldable predicates
data SizeLessThan (n :: Nat) Source #
A Predicate ensuring that the Foldable has a length
which is less than the specified type-level number.
Instances
| Generic (SizeLessThan n) Source # | |
Defined in Refined.Internal Associated Types type Rep (SizeLessThan n) :: Type -> Type # Methods from :: SizeLessThan n -> Rep (SizeLessThan n) x # to :: Rep (SizeLessThan n) x -> SizeLessThan n # | |
| (Foldable t, KnownNat n) => Predicate (SizeLessThan n) (t a) Source # | |
Defined in Refined.Internal | |
| type Rep (SizeLessThan n) Source # | |
Defined in Refined.Internal | |
data SizeGreaterThan (n :: Nat) Source #
A Predicate ensuring that the Foldable has a length
which is greater than the specified type-level number.
Instances
| Generic (SizeGreaterThan n) Source # | |
Defined in Refined.Internal Associated Types type Rep (SizeGreaterThan n) :: Type -> Type # Methods from :: SizeGreaterThan n -> Rep (SizeGreaterThan n) x # to :: Rep (SizeGreaterThan n) x -> SizeGreaterThan n # | |
| (Foldable t, KnownNat n) => Predicate (SizeGreaterThan n) (t a) Source # | |
Defined in Refined.Internal | |
| type Rep (SizeGreaterThan n) Source # | |
Defined in Refined.Internal | |
data SizeEqualTo (n :: Nat) Source #
A Predicate ensuring that the Foldable has a length
which is equal to the specified type-level number.
Instances
| Generic (SizeEqualTo n) Source # | |
Defined in Refined.Internal Associated Types type Rep (SizeEqualTo n) :: Type -> Type # Methods from :: SizeEqualTo n -> Rep (SizeEqualTo n) x # to :: Rep (SizeEqualTo n) x -> SizeEqualTo n # | |
| (Foldable t, KnownNat n) => Predicate (SizeEqualTo n) (t a) Source # | |
Defined in Refined.Internal | |
| type Rep (SizeEqualTo n) Source # | |
Defined in Refined.Internal | |
IsList predicates
data Descending Source #
Instances
| Generic Descending Source # | |
Defined in Refined.Internal Associated Types type Rep Descending :: Type -> Type # | |
| (Foldable t, Ord a) => Predicate Descending (t a) Source # | |
Defined in Refined.Internal | |
| type Rep Descending Source # | |
Defined in Refined.Internal | |
Weakening
class Weaken from to where Source #
A typeclass containing "safe" conversions between refined predicates where the target is weaker than the source: that is, all values that satisfy the first predicate will be guarunteed to satisy the second.
Take care: writing an instance declaration for your custom predicates is
the same as an assertion that weaken is safe to use:
instance Weaken Pred1 Pred2
For most of the instances, explicit type annotations for the result value's type might be required.
Minimal complete definition
Nothing
Instances
| n <= m => Weaken (To n) (To m) Source # | |
| m <= n => Weaken (From n) (From m) Source # | |
| m <= n => Weaken (GreaterThan n) (From m) Source # | |
Defined in Refined.Internal | |
| m <= n => Weaken (GreaterThan n) (GreaterThan m) Source # | |
Defined in Refined.Internal Methods weaken :: Refined (GreaterThan n) x -> Refined (GreaterThan m) x Source # | |
| n <= m => Weaken (LessThan n) (To m) Source # | |
| n <= m => Weaken (LessThan n) (LessThan m) Source # | |
| m <= q => Weaken (FromTo n m) (To q) Source # | |
| p <= n => Weaken (FromTo n m) (From p) Source # | |
| (p <= n, m <= q) => Weaken (FromTo n m) (FromTo p q) Source # | |
andLeft :: Refined (And l r) x -> Refined l x Source #
This function helps type inference. It is equivalent to the following:
instance Weaken (And l r) l
andRight :: Refined (And l r) x -> Refined r x Source #
This function helps type inference. It is equivalent to the following:
instance Weaken (And l r) r
leftOr :: Refined l x -> Refined (Or l r) x Source #
This function helps type inference. It is equivalent to the following:
instance Weaken l (Or l r)
rightOr :: Refined r x -> Refined (Or l r) x Source #
This function helps type inference. It is equivalent to the following:
instance Weaken r (Or l r)
Error handling
RefineException
data RefineException Source #
An exception encoding the way in which a Predicate failed.
Constructors
| RefineNotException !TypeRep | A |
| RefineAndException !TypeRep !(These RefineException RefineException) | A |
| RefineOrException !TypeRep !RefineException !RefineException | A |
| RefineOtherException !TypeRep !(Doc Void) | A |
Instances
displayRefineException :: RefineException -> Doc ann Source #
Display a RefineException as a Doc ann
RefineT and RefineM
A monad transformer that adds s to other monads.RefineException
The and pure functions yield computations that produce
the given value, while return sequences two subcomputations, exiting
on the first >>=.RefineException
Instances
| MonadTrans RefineT Source # | |
Defined in Refined.Internal | |
| Monad m => MonadError RefineException (RefineT m) Source # | |
Defined in Refined.Internal Methods throwError :: RefineException -> RefineT m a # catchError :: RefineT m a -> (RefineException -> RefineT m a) -> RefineT m a # | |
| Monad m => Monad (RefineT m) Source # | |
| Functor m => Functor (RefineT m) Source # | |
| MonadFix m => MonadFix (RefineT m) Source # | |
Defined in Refined.Internal | |
| Monad m => Applicative (RefineT m) Source # | |
| Generic1 (RefineT m :: Type -> Type) Source # | |
| Generic (RefineT m a) Source # | |
| type Rep1 (RefineT m :: Type -> Type) Source # | |
Defined in Refined.Internal | |
| type Rep (RefineT m a) Source # | |
Defined in Refined.Internal type Rep (RefineT m a) = D1 (MetaData "RefineT" "Refined.Internal" "refined-0.4.1-EYHUGtdk1BQEdvdCeXV31J" True) (C1 (MetaCons "RefineT" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (ExceptT RefineException m a)))) | |
runRefineT :: RefineT m a -> m (Either RefineException a) Source #
The inverse of .RefineT
mapRefineT :: (m (Either RefineException a) -> n (Either RefineException b)) -> RefineT m a -> RefineT n b Source #
Map the unwrapped computation using the given function.
runRefineT(mapRefineTf m) = f (runRefineTm)
refineM :: Either RefineException a -> RefineM a Source #
Constructs a computation in the RefineM monad. (The inverse of ).runRefineM
runRefineM :: RefineM a -> Either RefineException a Source #
Run a monadic action of type ,
yielding an RefineM a.Either RefineException a
This is just defined as .runIdentity . runRefineT
throwRefine :: Monad m => RefineException -> RefineT m a Source #
One can use inside of a monadic
context to begin processing a throwRefine.RefineException
catchRefine :: Monad m => RefineT m a -> (RefineException -> RefineT m a) -> RefineT m a Source #
A handler function to handle previous s
and return to normal execution. A common idiom is:RefineException
do { action1; action2; action3 } `catchRefine' handlerwhere the action functions can call . Note that
handler and the do-block must have the same return type.throwRefine
throwRefineOtherException Source #
Arguments
| :: Monad m | |
| => TypeRep | The |
| -> Doc Void | A |
| -> RefineT m a |
A handler for a .RefineException
throwRefineOtherException is useful for defining what
behaviour validate should have in the event of a predicate failure.