Safe Haskell | None |
---|---|
Language | Haskell2010 |
Data.Row.Dictionaries
Contents
Description
This module exports various dictionaries that help the type-checker when dealing with row-types.
For the various axioms, type variables are consistently in the following order:
- Any types that do not belong later.
- Labels
Row-types
- If applicable, the type in the row-type at the given label goes after each row-type
- Constraints
Synopsis
- uniqueMap :: forall {k1} {k2} (f :: k1 -> k2) (r :: Row k1). Dict (AllUniqueLabels (Map f r) ≈ AllUniqueLabels r)
- uniqueAp :: forall {k1} {k2} (fs :: Row (k1 -> k2)) (r :: Row k1). Dict (AllUniqueLabels (Ap fs r) ≈ AllUniqueLabels r)
- uniqueApSingle :: forall {a} {k} (x :: a) (r :: Row (a -> k)). Dict (AllUniqueLabels (ApSingle r x) ≈ AllUniqueLabels r)
- uniqueZip :: forall (r1 :: Row Type) (r2 :: Row Type). Dict (AllUniqueLabels (Zip r1 r2) ≈ (AllUniqueLabels r1, AllUniqueLabels r2))
- extendHas :: forall {k} (l :: Symbol) (t :: k) (r :: Row k). Dict ((Extend l t r .! l) ≈ t)
- mapHas :: forall {k} {b} (f :: k -> b) (l :: Symbol) (t :: k) (r :: Row k). ((r .! l) ≈ t) :- ((Map f r .! l) ≈ f t, (Map f r .- l) ≈ Map f (r .- l))
- apHas :: forall {k} {b} (l :: Symbol) (f :: k -> b) (ϕ :: Row (k -> b)) (t :: k) (ρ :: Row k). ((ϕ .! l) ≈ f, (ρ .! l) ≈ t) :- ((Ap ϕ ρ .! l) ≈ f t, (Ap ϕ ρ .- l) ≈ Ap (ϕ .- l) (ρ .- l))
- apSingleHas :: forall {a} {b} (x :: a) (l :: Symbol) (f :: a -> b) (r :: Row (a -> b)). ((r .! l) ≈ f) :- ((ApSingle r x .! l) ≈ f x, (ApSingle r x .- l) ≈ ApSingle (r .- l) x)
- mapExtendSwap :: forall {k} {b} (f :: k -> b) (ℓ :: Symbol) (τ :: k) (r :: Row k). Dict (Extend ℓ (f τ) (Map f r) ≈ Map f (Extend ℓ τ r))
- apExtendSwap :: forall {k} {b} (ℓ :: Symbol) (f :: k -> b) (fs :: Row (k -> b)) (τ :: k) (r :: Row k). Dict (Extend ℓ (f τ) (Ap fs r) ≈ Ap (Extend ℓ f fs) (Extend ℓ τ r))
- apSingleExtendSwap :: forall {a} {b} (τ :: a) (ℓ :: Symbol) (f :: a -> b) (r :: Row (a -> b)). Dict (Extend ℓ (f τ) (ApSingle r τ) ≈ ApSingle (Extend ℓ f r) τ)
- zipExtendSwap :: forall (ℓ :: Symbol) τ1 (r1 :: Row Type) τ2 (r2 :: Row Type). Dict (Extend ℓ (τ1, τ2) (Zip r1 r2) ≈ Zip (Extend ℓ τ1 r1) (Extend ℓ τ2 r2))
- mapMinJoin :: forall {k} {b} (f :: k -> b) (r :: Row k) (r' :: Row k). Dict ((Map f r .\/ Map f r') ≈ Map f (r .\/ r'))
- apSingleMinJoin :: forall {a} {b} (r :: Row (a -> b)) (r' :: Row (a -> b)) (x :: a). Dict ((ApSingle r x .\/ ApSingle r' x) ≈ ApSingle (r .\/ r') x)
- type FreeForall (r :: Row k) = Forall r (Unconstrained1 :: k -> Constraint)
- type FreeBiForall (r1 :: Row k1) (r2 :: Row k2) = BiForall r1 r2 (Unconstrained2 :: k1 -> k2 -> Constraint)
- freeForall :: forall {k} (r :: Row k) (c :: k -> Constraint). Forall r c :- Forall r (Unconstrained1 :: k -> Constraint)
- mapForall :: forall {k1} {k2} (f :: k1 -> k2) (ρ :: Row k1) (c :: k1 -> Constraint). Forall ρ c :- Forall (Map f ρ) (IsA c f)
- apSingleForall :: forall {k1} {k2} (a :: k1) (fs :: Row (k1 -> k2)) (c :: (k1 -> k2) -> Constraint). Forall fs c :- Forall (ApSingle fs a) (ActsOn c a)
- subsetJoin :: forall {k} (r1 :: Row k) (r2 :: Row k) (s :: Row k). Dict ((Subset r1 s, Subset r2 s) ≈ Subset (r1 .+ r2) s)
- subsetJoin' :: forall {k} (r1 :: Row k) (r2 :: Row k) (s :: Row k). Dict ((Subset r1 s, Subset r2 s) ≈ Subset (r1 .// r2) s)
- subsetRestrict :: forall {k} (r :: Row k) (s :: Row k) (l :: Symbol). Subset r s :- Subset (r .- l) s
- subsetTrans :: forall {k} (r1 :: Row k) (r2 :: Row k) (r3 :: Row k). (Subset r1 r2, Subset r2 r3) :- Subset r1 r3
- mapDifference :: forall {k} {b} (f :: k -> b) (r :: Row k) (r' :: Row k). Dict ((Map f r .\\ Map f r') ≈ Map f (r .\\ r'))
- apSingleDifference :: forall {a} {b} (r :: Row (a -> b)) (r' :: Row (a -> b)) (x :: a). Dict ((ApSingle r x .\\ ApSingle r' x) ≈ ApSingle (r .\\ r') x)
- class IsA (c :: k -> Constraint) (f :: k -> k1) (a :: k1) where
- data As (c :: k -> Constraint) (f :: k -> k1) (a :: k1) where
- As :: forall {k} {k1} (c :: k -> Constraint) (f :: k -> k1) (a :: k1) (t :: k). (a ~ f t, c t) => As c f a
- class ActsOn (c :: (k -> k1) -> Constraint) (t :: k) (a :: k1) where
- data As' (c :: (k -> k1) -> Constraint) (t :: k) (a :: k1) where
- As' :: forall {k} {k1} (c :: (k -> k1) -> Constraint) (f :: k -> k1) (a :: k1) (t :: k). (a ~ f t, c f) => As' c t a
- data Dict a where
- newtype a :- b = Sub (a => Dict b)
- class HasDict c e | e -> c where
- (\\) :: HasDict c e => (c => r) -> e -> r
- withDict :: HasDict c e => e -> (c => r) -> r
- class Unconstrained
- class Unconstrained1 (a :: k)
- class Unconstrained2 (a :: k) (b :: k1)
Axioms
uniqueMap :: forall {k1} {k2} (f :: k1 -> k2) (r :: Row k1). Dict (AllUniqueLabels (Map f r) ≈ AllUniqueLabels r) #
Map preserves uniqueness of labels.
uniqueAp :: forall {k1} {k2} (fs :: Row (k1 -> k2)) (r :: Row k1). Dict (AllUniqueLabels (Ap fs r) ≈ AllUniqueLabels r) #
Ap preserves uniqueness of labels.
uniqueApSingle :: forall {a} {k} (x :: a) (r :: Row (a -> k)). Dict (AllUniqueLabels (ApSingle r x) ≈ AllUniqueLabels r) #
ApSingle preserves uniqueness of labels.
uniqueZip :: forall (r1 :: Row Type) (r2 :: Row Type). Dict (AllUniqueLabels (Zip r1 r2) ≈ (AllUniqueLabels r1, AllUniqueLabels r2)) #
Zip preserves uniqueness of labels.
extendHas :: forall {k} (l :: Symbol) (t :: k) (r :: Row k). Dict ((Extend l t r .! l) ≈ t) #
If we know that r
has been extended with l .== t
, then we know that this
extension at the label l
must be t
.
mapHas :: forall {k} {b} (f :: k -> b) (l :: Symbol) (t :: k) (r :: Row k). ((r .! l) ≈ t) :- ((Map f r .! l) ≈ f t, (Map f r .- l) ≈ Map f (r .- l)) #
This allows us to derive Map f r .! l ≈ f t
from r .! l ≈ t
apHas :: forall {k} {b} (l :: Symbol) (f :: k -> b) (ϕ :: Row (k -> b)) (t :: k) (ρ :: Row k). ((ϕ .! l) ≈ f, (ρ .! l) ≈ t) :- ((Ap ϕ ρ .! l) ≈ f t, (Ap ϕ ρ .- l) ≈ Ap (ϕ .- l) (ρ .- l)) #
This allows us to derive Ap ϕ ρ .! l ≈ f t
from ϕ .! l ≈ f
and ρ .! l ≈ t
apSingleHas :: forall {a} {b} (x :: a) (l :: Symbol) (f :: a -> b) (r :: Row (a -> b)). ((r .! l) ≈ f) :- ((ApSingle r x .! l) ≈ f x, (ApSingle r x .- l) ≈ ApSingle (r .- l) x) #
This allows us to derive ApSingle r x .! l ≈ f x
from r .! l ≈ f
mapExtendSwap :: forall {k} {b} (f :: k -> b) (ℓ :: Symbol) (τ :: k) (r :: Row k). Dict (Extend ℓ (f τ) (Map f r) ≈ Map f (Extend ℓ τ r)) #
Proof that the Map
type family preserves labels and their ordering.
apExtendSwap :: forall {k} {b} (ℓ :: Symbol) (f :: k -> b) (fs :: Row (k -> b)) (τ :: k) (r :: Row k). Dict (Extend ℓ (f τ) (Ap fs r) ≈ Ap (Extend ℓ f fs) (Extend ℓ τ r)) #
Proof that the Ap
type family preserves labels and their ordering.
apSingleExtendSwap :: forall {a} {b} (τ :: a) (ℓ :: Symbol) (f :: a -> b) (r :: Row (a -> b)). Dict (Extend ℓ (f τ) (ApSingle r τ) ≈ ApSingle (Extend ℓ f r) τ) #
Proof that the ApSingle
type family preserves labels and their ordering.
zipExtendSwap :: forall (ℓ :: Symbol) τ1 (r1 :: Row Type) τ2 (r2 :: Row Type). Dict (Extend ℓ (τ1, τ2) (Zip r1 r2) ≈ Zip (Extend ℓ τ1 r1) (Extend ℓ τ2 r2)) #
Proof that the Ap
type family preserves labels and their ordering.
mapMinJoin :: forall {k} {b} (f :: k -> b) (r :: Row k) (r' :: Row k). Dict ((Map f r .\/ Map f r') ≈ Map f (r .\/ r')) #
Map distributes over MinJoin
apSingleMinJoin :: forall {a} {b} (r :: Row (a -> b)) (r' :: Row (a -> b)) (x :: a). Dict ((ApSingle r x .\/ ApSingle r' x) ≈ ApSingle (r .\/ r') x) #
ApSingle distributes over MinJoin
type FreeForall (r :: Row k) = Forall r (Unconstrained1 :: k -> Constraint) #
FreeForall
can be used when a Forall
constraint is necessary but there
is no particular constraint we care about.
type FreeBiForall (r1 :: Row k1) (r2 :: Row k2) = BiForall r1 r2 (Unconstrained2 :: k1 -> k2 -> Constraint) #
FreeForall
can be used when a BiForall
constraint is necessary but
there is no particular constraint we care about.
freeForall :: forall {k} (r :: Row k) (c :: k -> Constraint). Forall r c :- Forall r (Unconstrained1 :: k -> Constraint) #
Allow any Forall
over a row-type, be usable for Unconstrained1
.
mapForall :: forall {k1} {k2} (f :: k1 -> k2) (ρ :: Row k1) (c :: k1 -> Constraint). Forall ρ c :- Forall (Map f ρ) (IsA c f) #
This allows us to derive a Forall (Map f r) ..
from a Forall r ..
.
apSingleForall :: forall {k1} {k2} (a :: k1) (fs :: Row (k1 -> k2)) (c :: (k1 -> k2) -> Constraint). Forall fs c :- Forall (ApSingle fs a) (ActsOn c a) #
This allows us to derive a Forall (ApSingle f r) ..
from a Forall f ..
.
subsetJoin :: forall {k} (r1 :: Row k) (r2 :: Row k) (s :: Row k). Dict ((Subset r1 s, Subset r2 s) ≈ Subset (r1 .+ r2) s) #
Two rows are subsets of a third if and only if their disjoint union is a subset of that third.
subsetJoin' :: forall {k} (r1 :: Row k) (r2 :: Row k) (s :: Row k). Dict ((Subset r1 s, Subset r2 s) ≈ Subset (r1 .// r2) s) #
If two rows are each subsets of a third, their join is a subset of the third
subsetRestrict :: forall {k} (r :: Row k) (s :: Row k) (l :: Symbol). Subset r s :- Subset (r .- l) s #
If a row is a subset of another, then its restriction is also a subset of the other
subsetTrans :: forall {k} (r1 :: Row k) (r2 :: Row k) (r3 :: Row k). (Subset r1 r2, Subset r2 r3) :- Subset r1 r3 #
Subset is transitive
mapDifference :: forall {k} {b} (f :: k -> b) (r :: Row k) (r' :: Row k). Dict ((Map f r .\\ Map f r') ≈ Map f (r .\\ r')) #
Map distributes over Difference
apSingleDifference :: forall {a} {b} (r :: Row (a -> b)) (r' :: Row (a -> b)) (x :: a). Dict ((ApSingle r x .\\ ApSingle r' x) ≈ ApSingle (r .\\ r') x) #
ApSingle distributes over Difference
Helper Types
class IsA (c :: k -> Constraint) (f :: k -> k1) (a :: k1) where #
A class to capture the idea of As
so that it can be partially applied in
a context.
Instances
c a => IsA (c :: k1 -> Constraint) (f :: k1 -> k2) (f a :: k2) # | |
Defined in Data.Row.Dictionaries |
data As (c :: k -> Constraint) (f :: k -> k1) (a :: k1) where #
This data type is used to for its ability to existentially bind a type
variable. Particularly, it says that for the type a
, there exists a t
such that a ~ f t
and c t
holds.
Constructors
As :: forall {k} {k1} (c :: k -> Constraint) (f :: k -> k1) (a :: k1) (t :: k). (a ~ f t, c t) => As c f a |
class ActsOn (c :: (k -> k1) -> Constraint) (t :: k) (a :: k1) where #
A class to capture the idea of As'
so that it can be partially applied in
a context.
Instances
c f => ActsOn (c :: (k1 -> k2) -> Constraint) (t :: k1) (f t :: k2) # | |
Defined in Data.Row.Dictionaries |
data As' (c :: (k -> k1) -> Constraint) (t :: k) (a :: k1) where #
Like As
, but here we know the underlying value is some f
applied to the
given type a
.
Constructors
As' :: forall {k} {k1} (c :: (k -> k1) -> Constraint) (f :: k -> k1) (a :: k1) (t :: k). (a ~ f t, c f) => As' c t a |
Re-exports
Values of type
capture a dictionary for a constraint of type Dict
pp
.
e.g.
Dict
::Dict
(Eq
Int
)
captures a dictionary that proves we have an:
instanceEq
Int
Pattern matching on the Dict
constructor will bring this instance into scope.
Instances
() :=> (Semigroup (Dict a)) | |
() :=> (Show (Dict a)) | |
() :=> (Eq (Dict a)) | |
() :=> (Ord (Dict a)) | |
a :=> (Monoid (Dict a)) | |
a :=> (Bounded (Dict a)) | |
a :=> (Enum (Dict a)) | |
a :=> (Read (Dict a)) | |
HasDict a (Dict a) | |
Defined in Data.Constraint | |
(Typeable p, p) => Data (Dict p) | |
Defined in Data.Constraint Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Dict p -> c (Dict p) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Dict p) # toConstr :: Dict p -> Constr # dataTypeOf :: Dict p -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Dict p)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Dict p)) # gmapT :: (forall b. Data b => b -> b) -> Dict p -> Dict p # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Dict p -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Dict p -> r # gmapQ :: (forall d. Data d => d -> u) -> Dict p -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Dict p -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Dict p -> m (Dict p) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Dict p -> m (Dict p) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Dict p -> m (Dict p) # | |
a => Monoid (Dict a) | |
Semigroup (Dict a) | |
a => Bounded (Dict a) | |
a => Enum (Dict a) | |
Defined in Data.Constraint | |
a => Read (Dict a) | |
Show (Dict a) | |
c => Boring (Dict c) | |
Defined in Data.Constraint | |
NFData (Dict c) | |
Defined in Data.Constraint | |
Eq (Dict a) | |
Ord (Dict a) | |
This is the type of entailment.
a
is read as :-
ba
"entails" b
.
With this we can actually build a category for Constraint
resolution.
e.g.
Because
is a superclass of Eq
a
, we can show that Ord
a
entails Ord
a
.Eq
a
Because instance
exists, we can show that Ord
a => Ord
[a]
entails Ord
a
as well.Ord
[a]
This relationship is captured in the :-
entailment type here.
Since p
and entailment composes, :-
p:-
forms the arrows of a
Category
of constraints. However, Category
only became sufficiently
general to support this instance in GHC 7.8, so prior to 7.8 this instance
is unavailable.
But due to the coherence of instance resolution in Haskell, this Category
has some very interesting properties. Notably, in the absence of
IncoherentInstances
, this category is "thin", which is to say that
between any two objects (constraints) there is at most one distinguishable
arrow.
This means that for instance, even though there are two ways to derive
, the answers from these two paths _must_ by
construction be equal. This is a property that Haskell offers that is
pretty much unique in the space of languages with things they call "type
classes".Ord
a :-
Eq
[a]
What are the two ways?
Well, we can go from
via the
superclass relationship, and then from Ord
a :-
Eq
a
via the
instance, or we can go from Eq
a :-
Eq
[a]
via the instance
then from Ord
a :-
Ord
[a]
through the superclass relationship
and this diagram by definition must "commute".Ord
[a] :-
Eq
[a]
Diagrammatically,
Ord a ins / \ cls v v Ord [a] Eq a cls \ / ins v v Eq [a]
This safety net ensures that pretty much anything you can write with this library is sensible and can't break any assumptions on the behalf of library authors.
Instances
Category (:-) | Possible since GHC 7.8, when |
() :=> (Show (a :- b)) | |
() :=> (Eq (a :- b)) | |
() :=> (Ord (a :- b)) | |
a => HasDict b (a :- b) | |
Defined in Data.Constraint | |
(Typeable p, Typeable q, p => q) => Data (p :- q) | |
Defined in Data.Constraint Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> (p :- q) -> c (p :- q) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (p :- q) # toConstr :: (p :- q) -> Constr # dataTypeOf :: (p :- q) -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (p :- q)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (p :- q)) # gmapT :: (forall b. Data b => b -> b) -> (p :- q) -> p :- q # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> (p :- q) -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> (p :- q) -> r # gmapQ :: (forall d. Data d => d -> u) -> (p :- q) -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> (p :- q) -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> (p :- q) -> m (p :- q) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> (p :- q) -> m (p :- q) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> (p :- q) -> m (p :- q) # | |
Show (a :- b) | |
a => NFData (a :- b) | |
Defined in Data.Constraint | |
Eq (a :- b) | Assumes |
Ord (a :- b) | Assumes |
Defined in Data.Constraint |
class HasDict c e | e -> c where #
Witnesses that a value of type e
contains evidence of the constraint c
.
Mainly intended to allow (\\
) to be overloaded, since it's a useful operator.
(\\) :: HasDict c e => (c => r) -> e -> r infixl 1 #
Operator version of withDict
, with the arguments flipped
withDict :: HasDict c e => e -> (c => r) -> r #
From a Dict
, takes a value in an environment where the instance
witnessed by the Dict
is in scope, and evaluates it.
Essentially a deconstruction of a Dict
into its continuation-style
form.
Can also be used to deconstruct an entailment, a
, using a context :-
ba
.
withDict ::Dict
c -> (c => r) -> r withDict :: a => (a:-
c) -> (c => r) -> r
class Unconstrained1 (a :: k) #
A null constraint of one argument
Instances
Unconstrained1 (a :: k) # | |
Defined in Data.Row.Internal |
class Unconstrained2 (a :: k) (b :: k1) #
A null constraint of two arguments
Instances
Unconstrained2 (a :: k1) (b :: k2) # | |
Defined in Data.Row.Internal |