Guarantees
Clef.RFC0001.Constraints
Rests on Types.tycon_eq_dec, Types.tyconThe 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.
Rests on Types.tycon_eq_dec, Types.tyconA type satisfies the intersection if and only if it satisfies both constraints, so replacing two
constraints by their intersection changes no program's meaning.
Rests on Types.tycon_eq_dec, Types.tyconIt 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.
Rests on Types.tycon_eq_dec, Types.tyconWhen two constraints share no member, no instantiation satisfies both, so reporting an error is the
only sound outcome.
Rests on Types.tycon_eq_dec, Types.tyconWhen exactly one type is left, every instantiation that satisfies both constraints is that type, so
the solver may replace the variable by it.
Clef.RFC0001.TypeCase
Rests on Witnesses.witness, Types.tycon_eq_dec, Types.tycon, Witnesses.opThis is derived satisfaction. When the check passes at the definition, every type that satisfies
the constraint yields a specialization with the declared type. A call site is never the first place
where an operation on the constrained variable is found unsupported.
Rests on Witnesses.witness, Types.tycon_eq_dec, Types.tycon, Witnesses.opWhen the check fails, there is a member at which the body is not well typed. The diagnostic can
name it.
Rests on Witnesses.witness, Types.tycon_eq_dec, Types.tycon, Witnesses.opA body that checks against a member set checks against every set that entails it. Removing a member
from a constraint never breaks the definition, so only adding one can.
Rests on Witnesses.witness, Types.tycon_eq_dec, Types.tycon, Witnesses.opInside a body whose variable has one member set, calling a definition that was checked against
another is sound when the first entails the second. Every type the caller can be instantiated to is
one the callee was checked at.
Rests on Witnesses.witness, Types.tycon_eq_dec, Types.tycon, Witnesses.opA body that applies one operation to its parameter checks if and only if each member has a witness
for that operation with the declared result type. The result type may mention the variable, which
is how x + x has type 'T at both int and float.
Rests on Types.tycon_eq_dec, Types.tycon, Witnesses.op, Runtime.atom, Witnesses.applyWhenever a body specializes at a type, the specialization returns exactly what the reference
meaning returns at that type, on every input. The reference meaning inspects the instantiating
type and the specialization has no access to it. The static type-case is therefore erased
completely: no run-time test, tag or type argument is needed to implement it.
Rests on Witnesses.witness_sound, Witnesses.witness, Types.tycon, Witnesses.op, Runtime.atom, Witnesses.applyEvaluation of a specialization that has a type never gets stuck, and the value it returns has that
type. This rests on the assumption that every witness is implemented at its declared type.
Rests on Witnesses.witness_sound, Witnesses.witness, Types.tycon_eq_dec, Types.tycon, Witnesses.op, Runtime.atom, Witnesses.applyTake a definition whose check passes, any type satisfying its constraint, and arguments of the
parameter types at that type. The definition's meaning at that type is a value of the declared
result type. The check at the definition is all that is needed: nothing is checked again at a call
site or at run time.
Rests on Types.tycon_eq_dec, Types.tycon, Witnesses.opIts specialization does not depend on the instantiating type. Only a type-case can make a
set-constrained definition behave differently per member, so the loss of uniformity is confined to
bodies that ask for it.
Rests on Types.tycon_eq_dec, Types.tycon, Witnesses.op, Runtime.atom, Witnesses.applyIts meaning is the same at every type, on every input. A set-constrained definition that does not
use a type-case is as uniform as an unconstrained one.
Rests on Types.tycon_eq_dec, Types.tycon, Witnesses.opWhen each type-case tests every member, saturation finds an arm for every instantiating type that
satisfies the constraint. No instantiation is left without code.