Clef.RFC0001.Constraints
Closed-set constraints
The constraint form, and the rules by which the solver decides it.
constraint :=
...
typar : ( type | ... | type ) -- closed-set constraint
The parenthesised list holds at least two types. The form is told apart from a member constraint
and a default constructor constraint by its first token, which is never member, static or
new. A definition is not required to be inline on account of a closed-set constraint.
3
From Stdlib Require Import List.
Import ListNotations.
From Clef Require Import Spec.Types.Member sets
The member set of a closed-set constraint: the closed types it lists.
Definition cset : Type := list ty.References
Uses
- ty
- list
A member set is well formed when no member is listed twice and there are at least two. Members are
closed types by construction, since ty has no type variable. Member identity is type identity, so
whatever distinguishes two types distinguishes two members.
Definition well_formed (C : cset) : Prop :=
Definition well_formed (C : cset) : Prop :=
NoDup C /\ 2 <= length C.References
Uses
- cset
- length
- NoDup
A member set is not a type. cset is not ty, and no constructor of ty holds one, so a member
set cannot appear in type position and no expression has one as its type.
Satisfaction
A closed type satisfies a constraint exactly when it is a member. Coercion plays no part.
Whether a closed type is a member, as the solver computes it.
The computed test agrees with membership.
Satisfaction is decidable, so a constraint on a concrete type is never left unresolved.
Entailment
Whether every member of one set is a member of another, as the solver computes it.
A variable constrained to one member set may be used where another member set is required exactly when the subset test passes.
Entailment is exactly preservation of satisfaction.
The subset test accepts a use of a constrained variable if and only if every type the variable can be instantiated to satisfies the required constraint. It rejects nothing sound and accepts nothing unsound.
References
A constraint entails itself.
Lemma entails_refl (C : cset) : entails C C.
Qed
Proof.
apply entails_iff_sat. intros t H. exact H.
Qed.References
Entailment chains.
Lemma entails_trans (C D E : cset) : entails C D -> entails D E -> entails C E.
Qed
Proof.
rewrite !entails_iff_sat. intros H1 H2 t H. apply H2. apply H1. exact H.
Qed.References
Intersection
When unification gives one variable two closed-set constraints, they are replaced by one whose member set is the intersection.
The members of the first set that are also members of the second.
Intersecting two constraints loses no information.
A type satisfies the intersection if and only if it satisfies both constraints, so replacing two constraints by their intersection changes no program's meaning.
The intersection is the weakest constraint that entails both.
It entails each of the two constraints, and any constraint that entails both of them entails it. The solver therefore makes the most general choice, which is what principal types need.
Arguments
Theorem meet_greatest (C D E : cset) :
Theorem meet_greatest (C D E : cset) :
entails (meet C D) C /\ entails (meet C D) D /\
(entails E C -> entails E D -> entails E (meet C D)).
Arguments
Qed
Proof.
split; [| split].
- apply entails_iff_sat. intros t H. apply meet_sat in H. apply H.
- apply entails_iff_sat. intros t H. apply meet_sat in H. apply H.
- rewrite !entails_iff_sat. intros HC HD t H. apply meet_sat. split.
+ apply HC. exact H.
+ apply HD. exact H.
Qed.References
An empty intersection admits no type.
When two constraints share no member, no instantiation satisfies both, so reporting an error is the only sound outcome.
Qed
Proof.
intros E t H. apply meet_sat in H. rewrite E in H. exact H.
Qed.An intersection of one type solves the variable.
When exactly one type is left, every instantiation that satisfies both constraints is that type, so the solver may replace the variable by it.
Intersection lists no member twice when its first argument lists none twice.
Origin and signatures
Two rules of this section are stated in prose only.
- Origin. A closed-set constraint comes only from an explicit declaration. It is never synthesised from the operations a definition uses. It propagates through unification as other constraints do, and may appear in an inferred generalized type.
- Signatures. A closed-set constraint is part of a value's type and appears in its signature. Signature conformance requires equal member sets.