Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Traits are optional attributes associated with a value. For
example, a list containing totally ordered values might have a
Maximum
trait where the associated attribute is the maximum
value. This trait exists only if the list is non-empty. The Trait
typeclass provides an interface to extract such trait attributes.
Traits help to link attributes with values in a type-safe manner.
Traits are somewhat similar to refinement types, but allow arbitrary attributes to be associated with a value instead of only a predicate.
Synopsis
- class Trait (t :: Type) a where
- class Trait t a => TraitAbsence t a where
- class (Arrow h, TraitAbsence t a) => Get h t a where
- type family Gets h ts a :: Constraint where ...
- data Linked (ts :: [Type]) a
- class (Arrow h, Trait t a) => Set h (t :: Type) a where
- type family Sets h ts a :: Constraint where ...
- linkzero :: a -> Linked '[] a
- linkminus :: Linked (t ': ts) a -> Linked ts a
- unlink :: Linked ts a -> a
- probe :: forall t ts h a. Get h t a => t -> h (Linked ts a) (Either (Absence t a) (Linked (t ': ts) a))
- plant :: forall t ts h a. Set h t a => t -> h (Linked ts a, Attribute t a) (Linked (t ': ts) a)
- class HasTrait t ts where
- type family HaveTraits ts qs :: Constraint where ...
- pick :: Tagged t a -> a
- type MissingTrait t = ((((((((Text "The request doesn't have the trait \8216" :<>: ShowType t) :<>: Text "\8217.") :$$: Text "") :$$: Text "Did you use a wrong trait type?") :$$: Text "For e.g., \8216QueryParam \"foo\" Int\8217 instead of \8216QueryParam \"foo\" String\8217?") :$$: Text "") :$$: Text "Or did you forget to apply an appropriate middleware?") :$$: Text "For e.g. The trait \8216JSONBody t\8217 can be used with \8216jsonRequestBody @t\8217 middleware.") :$$: Text ""
Core Types
class Trait (t :: Type) a Source #
A trait is an attribute t
associated with a value a
.
type Attribute t a :: Type Source #
Type of the associated attribute when the trait holds for a value
Instances
class Trait t a => TraitAbsence t a Source #
A trait t
that can be retrieved from a
but could be absent.
type Absence t a :: Type Source #
Type that indicates that the trait does not exist for a value. This could be an error message, exception etc.
Instances
class (Arrow h, TraitAbsence t a) => Get h t a where Source #
Extract trait attributes from a value.
type family Gets h ts a :: Constraint where ... Source #
Gets h ts a
is equivalent to (Get h t1 a, Get h t2 a, ..., Get
h tn a)
where ts = [t1, t2, ..., tn]
.
class (Arrow h, Trait t a) => Set h (t :: Type) a where Source #
Set a trait attribute on a value
:: t | The trait to set |
-> (Linked ts a -> a -> Attribute t a -> Linked (t ': ts) a) | A function to generate a linked value. This function must be
called by the |
-> h (Linked ts a, Attribute t a) (Linked (t ': ts) a) | An arrow that attches a new trait attribute to a value linked with other traits |
Set a trait attribute t
on the value a
.
type family Sets h ts a :: Constraint where ... Source #
Sets h ts a
is equivalent to (Set h t1 a, Set h t2 a, ..., Set
h tn a)
where ts = [t1, t2, ..., tn]
.
Linking values with attributes
probe :: forall t ts h a. Get h t a => t -> h (Linked ts a) (Either (Absence t a) (Linked (t ': ts) a)) Source #
Attempt to link an additional trait with an already linked
value. This can fail indicating an Absence
of the trait.
plant :: forall t ts h a. Set h t a => t -> h (Linked ts a, Attribute t a) (Linked (t ': ts) a) Source #
Set a trait attribute on linked value to produce another linked value
Retrive trait attributes from linked values
class HasTrait t ts where Source #
Constraint that proves that the trait t
is present in the list
of traits ts
.
from :: Linked ts a -> Tagged t (Attribute t a) Source #
Get the attribute associated with t
from a linked value. See also: pick
.
type family HaveTraits ts qs :: Constraint where ... Source #
Constraint that proves that all the traits in the list ts
are
also present in the list qs
.
HaveTraits '[] qs = () | |
HaveTraits (t ': ts) qs = (HasTrait t qs, HaveTraits ts qs) |
pick :: Tagged t a -> a Source #
Retrieve a trait.
pick
is used along with from
to retrieve an attribute from a
linked value:
pick @t $ from val
type MissingTrait t = ((((((((Text "The request doesn't have the trait \8216" :<>: ShowType t) :<>: Text "\8217.") :$$: Text "") :$$: Text "Did you use a wrong trait type?") :$$: Text "For e.g., \8216QueryParam \"foo\" Int\8217 instead of \8216QueryParam \"foo\" String\8217?") :$$: Text "") :$$: Text "Or did you forget to apply an appropriate middleware?") :$$: Text "For e.g. The trait \8216JSONBody t\8217 can be used with \8216jsonRequestBody @t\8217 middleware.") :$$: Text "" Source #
Type error for nicer UX of missing traits