| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Refined.Internal
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/
Synopsis
- newtype Refined p x = Refined x
- refine :: Predicate p x => x -> Either RefineException (Refined p x)
- refine_ :: forall p x. Predicate p x => x -> Either RefineException 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))
- refineTH_ :: forall p x. (Predicate p x, Lift x) => x -> Q (TExp x)
- unrefine :: Refined p x -> x
- class Typeable p => Predicate p x where
- reifyPredicate :: forall p a. Predicate p a => a -> Bool
- data Not p = Not
- data And l r = And
- type (&&) = And
- data Or l r = Or
- type (||) = Or
- data IdPred = IdPred
- data LessThan (n :: Nat) = LessThan
- data GreaterThan (n :: Nat) = GreaterThan
- data From (n :: Nat) = From
- data To (n :: Nat) = To
- data FromTo (mn :: Nat) (mx :: Nat) = FromTo
- data NegativeFromTo (n :: Nat) (m :: Nat) = NegativeFromTo
- data EqualTo (n :: Nat) = EqualTo
- data NotEqualTo (n :: Nat) = NotEqualTo
- data Odd = Odd
- data Even = Even
- data DivisibleBy (n :: Nat) = DivisibleBy
- 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) = SizeLessThan
- data SizeGreaterThan (n :: Nat) = SizeGreaterThan
- data SizeEqualTo (n :: Nat) = SizeEqualTo
- type NonEmpty = SizeGreaterThan 0
- data Ascending = Ascending
- data Descending = 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
- strengthen :: forall p p' x. (Predicate p x, Predicate p' x) => Refined p x -> Either RefineException (Refined (p && p') x)
- strengthenM :: forall p p' x m. (Predicate p x, Predicate p' x, Monad m) => Refined p x -> RefineT m (Refined (p && p') x)
- data RefineException
- displayRefineException :: RefineException -> Doc ann
- data RefineT m a
- runRefineT :: RefineT m a -> m (Either RefineException a)
- exceptRefine :: Monad m => Either RefineException a -> RefineT m 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
- (|>) :: a -> (a -> b) -> b
- (.>) :: (a -> b) -> (b -> c) -> a -> c
- 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.
Constructors
| Refined x |
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, Typeable a, Typeable p, 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.
refine_ :: forall p x. Predicate p x => x -> Either RefineException x Source #
Like refine, but discards the refinement.
This _can_ be useful when you only need to validate
that some value at runtime satisfies some predicate.
See also reifyPredicate.
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 Int Refined 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 IntIf 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/
refineTH_ :: forall p x. (Predicate p x, Lift x) => x -> Q (TExp x) Source #
Like refineTH, but immediately unrefines the value.
This is useful when some value need only be refined
at compile-time.
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
reifyPredicate :: forall p a. Predicate p a => a -> Bool Source #
Reify a Predicate by turning it into a value-level predicate.
Logical predicates
The negation of a predicate.
>>>isRight (refine @(Not NonEmpty) @[Int] [])True
>>>isLeft (refine @(Not NonEmpty) @[Int] [1,2])True
Constructors
| Not |
The conjunction of two predicates.
>>>isLeft (refine @(And Positive Negative) @Int 3)True
>>>isRight (refine @(And Positive Odd) @Int 203)True
Constructors
| And |
The disjunction of two predicates.
>>>isRight (refine @(Or Even Odd) @Int 3)True
>>>isRight (refine @(Or (LessThan 3) (GreaterThan 3)) @Int 2)True
Constructors
| Or |
Identity predicate
A predicate which is satisfied for all types.
Arguments passed to in validate
are not evaluated.validate IdPred x
>>>isRight (refine @IdPred @Int undefined)True
>>>isLeft (refine @IdPred @Int undefined)False
Constructors
| IdPred |
Numeric predicates
data LessThan (n :: Nat) Source #
A Predicate ensuring that the value is less than the
specified type-level number.
>>>isRight (refine @(LessThan 12) @Int 11)True
>>>isLeft (refine @(LessThan 12) @Int 12)True
Constructors
| LessThan |
data GreaterThan (n :: Nat) Source #
A Predicate ensuring that the value is greater than the
specified type-level number.
>>>isRight (refine @(GreaterThan 65) @Int 67)True
>>>isLeft (refine @(GreaterThan 65) @Int 65)True
Constructors
| GreaterThan |
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 # | |
A Predicate ensuring that the value is greater than or equal to the
specified type-level number.
>>>isRight (refine @(From 9) @Int 10)True
>>>isRight (refine @(From 10) @Int 10)True
>>>isLeft (refine @(From 11) @Int 10)True
Constructors
| From |
A Predicate ensuring that the value is less than or equal to the
specified type-level number.
>>>isRight (refine @(To 23) @Int 17)True
>>>isLeft (refine @(To 17) @Int 23)True
Constructors
| To |
data FromTo (mn :: Nat) (mx :: Nat) Source #
A Predicate ensuring that the value is within an inclusive range.
>>>isRight (refine @(FromTo 0 16) @Int 13)True
>>>isRight (refine @(FromTo 13 15) @Int 13)True
>>>isRight (refine @(FromTo 13 15) @Int 15)True
>>>isLeft (refine @(FromTo 13 15) @Int 12)True
Constructors
| FromTo |
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 NegativeFromTo (n :: Nat) (m :: Nat) Source #
A Predicate ensuring that the value is greater or equal than a negative
number specified as a type-level (positive) number n and less than a
type-level (positive) number m.
>>>isRight (refine @(NegativeFromTo 5 12) @Int (-3))True
>>>isLeft (refine @(NegativeFromTo 4 3) @Int (-5))True
Constructors
| NegativeFromTo |
Instances
| Generic (NegativeFromTo n m) Source # | |
Defined in Refined.Internal Associated Types type Rep (NegativeFromTo n m) :: Type -> Type # Methods from :: NegativeFromTo n m -> Rep (NegativeFromTo n m) x # to :: Rep (NegativeFromTo n m) x -> NegativeFromTo n m # | |
| (Ord x, Num x, KnownNat n, KnownNat m) => Predicate (NegativeFromTo n m) x Source # | |
Defined in Refined.Internal | |
| type Rep (NegativeFromTo n m) Source # | |
data EqualTo (n :: Nat) Source #
A Predicate ensuring that the value is equal to the specified
type-level number n.
>>>isRight (refine @(EqualTo 5) @Int 5)True
>>>isLeft (refine @(EqualTo 6) @Int 5)True
Constructors
| EqualTo |
data NotEqualTo (n :: Nat) Source #
A Predicate ensuring that the value is not equal to the specified
type-level number n.
>>>isRight (refine @(NotEqualTo 6) @Int 5)True
>>>isLeft (refine @(NotEqualTo 5) @Int 5)True
Constructors
| NotEqualTo |
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 # | |
A Predicate ensuring that the value is odd.
>>>isRight (refine @Odd @Int 33)True
>>>isLeft (refine @Odd @Int 32)True
Constructors
| Odd |
A Predicate ensuring that the value is even.
>>>isRight (refine @Even @Int 32)True
>>>isLeft (refine @Even @Int 33)True
Constructors
| Even |
data DivisibleBy (n :: Nat) Source #
A Predicate ensuring that the value is divisible by n.
>>>isRight (refine @(DivisibleBy 3) @Int 12)True
>>>isLeft (refine @(DivisibleBy 2) @Int 37)True
Constructors
| DivisibleBy |
Instances
| Generic (DivisibleBy n) Source # | |
Defined in Refined.Internal Associated Types type Rep (DivisibleBy n) :: Type -> Type # Methods from :: DivisibleBy n -> Rep (DivisibleBy n) x # to :: Rep (DivisibleBy n) x -> DivisibleBy n # | |
| (Integral x, KnownNat n) => Predicate (DivisibleBy n) x Source # | |
Defined in Refined.Internal | |
| type Rep (DivisibleBy n) Source # | |
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.
>>>isRight (refine @(SizeLessThan 4) @[Int] [1,2,3])True
>>>isLeft (refine @(SizeLessThan 5) @[Int] [1,2,3,4,5])True
Constructors
| SizeLessThan |
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 # | |
data SizeGreaterThan (n :: Nat) Source #
A Predicate ensuring that the Foldable has a length
which is greater than the specified type-level number.
>>>isLeft (refine @(SizeGreaterThan 3) @[Int] [1,2,3])True
>>>isRight (refine @(SizeGreaterThan 3) @[Int] [1,2,3,4,5])True
Constructors
| SizeGreaterThan |
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 # | |
data SizeEqualTo (n :: Nat) Source #
A Predicate ensuring that the Foldable has a length
which is equal to the specified type-level number.
>>>isRight (refine @(SizeEqualTo 4) @[Int] [1,2,3,4])True
>>>isLeft (refine @(SizeEqualTo 35) @[Int] [1,2,3,4])True
Constructors
| SizeEqualTo |
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 # | |
IsList predicates
A Predicate ensuring that the Foldable contains elements
in a strictly ascending order.
>>>isRight (refine @Ascending @[Int] [5, 8, 13, 21, 34])True
>>>isLeft (refine @Ascending @[Int] [34, 21, 13, 8, 5])True
Constructors
| Ascending |
data Descending Source #
A Predicate ensuring that the Foldable contains elements
in a strictly descending order.
>>>isRight (refine @Descending @[Int] [34, 21, 13, 8, 5])True
>>>isLeft (refine @Descending @[Int] [5, 8, 13, 21, 34])True
Constructors
| Descending |
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 # | |
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)
Strengthening
strengthen :: forall p p' x. (Predicate p x, Predicate p' x) => Refined p x -> Either RefineException (Refined (p && p') x) Source #
Strengthen a refinement by composing it with another.
strengthenM :: forall p p' x m. (Predicate p x, Predicate p' x, Monad m) => Refined p x -> RefineT m (Refined (p && p') x) Source #
Strengthen a refinement by composing it with another
inside of the RefineT monad.
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.4-7xXnhN9HJ7XByi1PQY08Xe" 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
exceptRefine :: Monad m => Either RefineException a -> RefineT m a Source #
Constructor for computations in the movie.
(The inverse of RefineTrunRefineT).
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.
(.>) :: (a -> b) -> (b -> c) -> a -> c infixl 9 Source #
Helper function, stolen from the flow package.