Safe Haskell | Safe-Inferred |
---|---|
Language | GHC2021 |
Main import module for basic use.
For defining Strengthen
instances, import Strongweak.Strengthen.
Instance design
A given strong type a
has exactly one associated weak type
.
Multiple strong types may weaken to the same weak type.Weaken
a
The following laws must hold:
weaken
a ==weaken
b |= a == bstrengthen
(weaken
a) ==pure
a
strongweak is largely a programmer convenience library. There is a lot of room to write instances which may seem useful on first glance, but are inconsistent with the overall design. Here is some relevant guidance.
- Weak types should have _simpler invariants to manage_ than strong ones.
- In general, weak types should be easier to use than strong ones.
- Most (all?) instances should handle (relax or assert) a single invariant.
- Most instances should not have a recursive context.
Some types may not have any invariants which may be usefully relaxed e.g.
. For these, you may write a recursive instance that
weakens/strengthens "through" the type e.g. Either
a b(
). Don't combine the two instance types.Weaken
a, Weaken
b) => Weak
(Either
a b)
An example is
. We could weaken this to NonEmpty
a[a]
,
but also to [
. However, the latter would mean decomposing and
removing an invariant simultaneously. It would be two separate strengthens in
one instance. And now, your Weaken
a]a
must be in the strongweak ecosystem, which isn't
necessarily what you want - indeed, it appears this sort of design would require
a
overlapping instance, which I do not want. On the
other hand, Weaken
a = a, weaken = id[a]
does weaken to [
, because there are no invariants
present to remove, so decomposing is all the user could hope to do.Weaken
a]
Classes
Weaken some a
, relaxing certain invariants.
See Strongweak for class design notes and laws.
Instances
Weaken Int16 Source # | |
Weaken Int32 Source # | |
Weaken Int64 Source # | |
Weaken Int8 Source # | |
Weaken Word16 Source # | |
Weaken Word32 Source # | |
Weaken Word64 Source # | |
Weaken Word8 Source # | |
Weaken (Identity a) Source # | Strip wrapper. |
Weaken (NonEmpty a) Source # | Weaken non-empty lists into plain lists. |
Weaken a => Weaken [a] Source # | Decomposer. Weaken every element in a list. |
(Weaken a, Weaken b) => Weaken (Either a b) Source # | Decomposer. Weaken either side of an |
(Generic s, Generic w, GWeaken (Rep s) (Rep w)) => Weaken (GenericallySW s w) Source # | |
Defined in Strongweak.Generic.Via type Weak (GenericallySW s w) Source # weaken :: GenericallySW s w -> Weak (GenericallySW s w) Source # | |
(Weaken a, Weaken b) => Weaken (a, b) Source # | Decomposer. Weaken both elements of a tuple. |
Weaken (Const a b) Source # | Strip wrapper. |
Weaken (Refined p a) Source # | Strip refined type refinement. |
Vector v a => Weaken (Vector v n a) Source # | Weaken sized vectors into plain lists. |
Weaken (Refined1 p f a) Source # | Strip refined functor type refinement. |
class Weaken a => Strengthen a where Source #
Attempt to strengthen some
, asserting certain invariants.Weak
a
We take Weaken
as a superclass in order to maintain strong/weak type pair
consistency. We choose this dependency direction because we treat the strong
type as the "canonical" one, so Weaken
is the more natural (and
straightforward) class to define. That does mean the instances for this class
are a little confusingly worded. Alas.
See Strongweak for class design notes and laws.
strengthen :: Weak a -> Result a Source #
Attempt to strengthen some
to its associated strong type
Weak
aa
.
Instances
Other definitions
liftWeakF :: Weaken a => (Weak a -> b) -> a -> b Source #
Lift a function on a weak type to the associated strong type by weakening first.
Strength switch wrapper
Strength enumeration: is it strong, or weak?
Primarily interesting at the type level (using DataKinds).
type family SW (s :: Strength) a :: Type where ... Source #
Get either the strong or weak representation of a type, depending on the type-level "switch" provided.
This is intended to be used in data types that take a Strength
type. Define
your type using strong fields wrapped in SW s
. You then get the weak
representation for free, using the same definition.
data A (s :: Strength) = A { a1 :: SW s Word8 , a2 :: String }