RefinementTypes.Examples
Example: maximum
From Stdlib Require Import Lists.List.
Import ListNotations.
From Stdlib Require Import ZArith.BinInt.
Require Import RefinementTypes.Syntax.
Require Import RefinementTypes.Eval.
Require Import RefinementTypes.Subst.
Require Import RefinementTypes.SubstLemmas.
Require Import RefinementTypes.Wf.
Require Import RefinementTypes.WfLemmas.
Require Import RefinementTypes.Avoid.
Require Import RefinementTypes.FirstOrder.
Require Import RefinementTypes.Positivity.
Require Import RefinementTypes.SyntacticSubtyping.
Require Import RefinementTypes.SyntacticTyping.
Require Import RefinementTypes.SemanticSubtyping.
Require Import RefinementTypes.SemanticImplies.
Definition ListTy (tv : nat) : Ty :=
TMuAll (TSum TUnit (TSigma (TVar (S tv)) (TVar 0))).
Definition OptionTy (tv : nat) : Ty :=
TSum TUnit (TVar tv).
Definition OrderingTy (tv : nat) : Ty :=
TFun (TVar tv) (TFun (TVar tv) TBool).
Definition AccTy : Ty := TSigma (ListTy 0) (OptionTy 0).
Definition ResTy : Ty := OptionTy 0.
Definition ListTy_unfolded : Ty := TSum TUnit (TSigma (TVar 0) (ListTy 0)).
Definition maximum_ty : Ty :=
TForall TBot TTop
(TForall TBot (TVar 0)
(TFun (ListTy 0)
(TFun (OrderingTy 1)
(OptionTy 0)))).
Definition maximum_tm : Term :=
ttabs TBot TTop
(ttabs TBot (TVar 0)
(tabs (ListTy 0)
(tabs (OrderingTy 1)
(tloop
(tpair (tvar 1) (tinl (TVar 0) tunit))
(tmatch_pair (tvar 0)
(tmatch_sum (tvar 1)
(tinr AccTy (tvar 1))
(tmatch_pair (tvar 0)
(tmatch_sum (tvar 3)
(tinl ResTy
(tpair (tvar 1) (tinr TUnit (tvar 2))))
(tif (tapp (tapp (tvar 7) (tvar 0)) (tvar 2))
(tinl ResTy
(tpair (tvar 1) (tinr TUnit (tvar 2))))
(tinl ResTy
(tpair (tvar 1) (tinr TUnit (tvar 0)))))
))
)))))).
Fixpoint list_term (elems : list Term) : Term :=
match elems with
| [] ⇒ tinl TUnit tunit
| x :: xs ⇒ tinr TUnit (tpair x (list_term xs))
end.
Definition int_le : Term :=
tabs TInt32 (tabs TInt32 (tbin_op OpLe (tvar 1) (tvar 0))).
Definition test_maximum_nonempty : Term :=
tapp (tapp (ttapp (ttapp maximum_tm TInt32) TInt32)
(list_term (map tint32 [3%Z; 1%Z; 4%Z; 1%Z; 5%Z])))
int_le.
Compute (eval 1000 [] test_maximum_nonempty).
(* = Some (Some (vinr (vint32 5))) *)
Definition test_maximum_empty : Term :=
tapp (tapp (ttapp (ttapp maximum_tm TInt32) TInt32)
(list_term []))
int_le.
Compute (eval 1000 [] test_maximum_empty).
(* = Some (Some (vinl vunit)) *)
Definition test_maximum_singleton : Term :=
tapp (tapp (ttapp (ttapp maximum_tm TInt32) TInt32)
(list_term (map tint32 [42%Z])))
int_le.
Compute (eval 1000 [] test_maximum_singleton).
(* = Some (Some (vinr (vint32 42))) *)
Lemma U_sub_T : ∀ tbounds tenv facts,
nth_error tbounds 0 = Some (TBot, TVar 0) →
syn_subtype tbounds tenv facts (TVar 0) (TVar 1).
Proof.
intros × H.
replace (TVar 1) with (ren_ty (fun n ⇒ n + 1) id (TVar 0)) by reflexivity.
exact (SSub_TVar_Upper _ _ _ 0 TBot (TVar 0) H).
Qed.
Lemma tbounds_shift_term_hd : ∀ tb,
nth_error tb 0 = Some (TBot, TVar 0) →
nth_error (tbounds_shift_term tb) 0 = Some (TBot, TVar 0).
Proof.
intros [| [L U] tb'] H; simpl in *; try discriminate.
injection H as → →. reflexivity.
Qed.
nth_error tbounds 0 = Some (TBot, TVar 0) →
syn_subtype tbounds tenv facts (TVar 0) (TVar 1).
Proof.
intros × H.
replace (TVar 1) with (ren_ty (fun n ⇒ n + 1) id (TVar 0)) by reflexivity.
exact (SSub_TVar_Upper _ _ _ 0 TBot (TVar 0) H).
Qed.
Lemma tbounds_shift_term_hd : ∀ tb,
nth_error tb 0 = Some (TBot, TVar 0) →
nth_error (tbounds_shift_term tb) 0 = Some (TBot, TVar 0).
Proof.
intros [| [L U] tb'] H; simpl in *; try discriminate.
injection H as → →. reflexivity.
Qed.
List unfold: ListU <: Unit + (U, ListU)
Lemma list_unfold_sub : ∀ tbounds tenv facts,
syn_subtype tbounds tenv facts (ListTy 0) ListTy_unfolded.
Proof.
intros. unfold ListTy, ListTy_unfolded.
replace (TSum TUnit (TSigma (TVar 0) (TMuAll (TSum TUnit (TSigma (TVar 1) (TVar 0))))))
with (ty_subst (TSum TUnit (TSigma (TVar 1) (TVar 0)))
(TMuAll (TSum TUnit (TSigma (TVar 1) (TVar 0))))) by reflexivity.
apply SSub_Mu_Unfold. reflexivity.
Qed.
syn_subtype tbounds tenv facts (ListTy 0) ListTy_unfolded.
Proof.
intros. unfold ListTy, ListTy_unfolded.
replace (TSum TUnit (TSigma (TVar 0) (TMuAll (TSum TUnit (TSigma (TVar 1) (TVar 0))))))
with (ty_subst (TSum TUnit (TSigma (TVar 1) (TVar 0)))
(TMuAll (TSum TUnit (TSigma (TVar 1) (TVar 0))))) by reflexivity.
apply SSub_Mu_Unfold. reflexivity.
Qed.
OrderingT <: OrderingU by function contravariance and U <: T
Lemma ordering_sub : ∀ tbounds tenv facts,
nth_error tbounds 0 = Some (TBot, TVar 0) →
syn_subtype tbounds tenv facts (OrderingTy 1) (OrderingTy 0).
Proof.
intros × Hb. unfold OrderingTy.
apply SSub_Fun.
- apply U_sub_T. exact Hb.
- apply SSub_Fun.
+ apply U_sub_T. apply tbounds_shift_term_hd. exact Hb.
+ apply SSub_Refl.
Qed.
nth_error tbounds 0 = Some (TBot, TVar 0) →
syn_subtype tbounds tenv facts (OrderingTy 1) (OrderingTy 0).
Proof.
intros × Hb. unfold OrderingTy.
apply SSub_Fun.
- apply U_sub_T. exact Hb.
- apply SSub_Fun.
+ apply U_sub_T. apply tbounds_shift_term_hd. exact Hb.
+ apply SSub_Refl.
Qed.
TOr T T <: T
Lemma or_same_sub : ∀ tbounds tenv facts T,
syn_subtype tbounds tenv facts (TOr T T) T.
Proof. intros. apply SSub_Or; apply SSub_Refl. Qed.
syn_subtype tbounds tenv facts (TOr T T) T.
Proof. intros. apply SSub_Or; apply SSub_Refl. Qed.
Typing derivation
Type a variable by lookup.
ST_Var produces subst_ty TVar (tm_shift (S i)) T; for term-var-free types
this is convertible to T, so change succeeds.
Ltac type_var :=
match goal with
| |- syn_typed ?tb ?te ?f (tvar ?i) ?T ⇒
change T with (subst_ty TVar (tm_shift (S i)) T);
exact (ST_Var tb te f i T eq_refl)
end.
Theorem maximum_typed :
syn_typed [] [] [] maximum_tm maximum_ty.
Proof.
unfold maximum_tm, maximum_ty.
apply ST_TAbs. apply ST_TAbs. apply ST_Abs. apply ST_Abs. simpl.
(* --- tloop : ResTy --- *)
eapply ST_Loop with (A := AccTy) (B := ResTy); [reflexivity | reflexivity | | ].
- (* Initial value: (xs, inl(unit)) : AccTy *)
unfold AccTy.
change (TSigma (ListTy 0) (OptionTy 0))
with (TSigma (ListTy 0) (subst_ty TVar (abstract_term_var 1) (OptionTy 0))).
eapply ST_Pair.
+ type_var.
+ apply ST_Inl. apply ST_Unit.
- (* Loop body : TSum AccTy ResTy *)
(* The body is deeply nested pattern matches. We admit the inner
derivation for now — the key subtyping lemmas above (U_sub_T,
list_unfold_sub, ordering_sub, or_same_sub) are the interesting part. *)
admit.
Admitted.
match goal with
| |- syn_typed ?tb ?te ?f (tvar ?i) ?T ⇒
change T with (subst_ty TVar (tm_shift (S i)) T);
exact (ST_Var tb te f i T eq_refl)
end.
Theorem maximum_typed :
syn_typed [] [] [] maximum_tm maximum_ty.
Proof.
unfold maximum_tm, maximum_ty.
apply ST_TAbs. apply ST_TAbs. apply ST_Abs. apply ST_Abs. simpl.
(* --- tloop : ResTy --- *)
eapply ST_Loop with (A := AccTy) (B := ResTy); [reflexivity | reflexivity | | ].
- (* Initial value: (xs, inl(unit)) : AccTy *)
unfold AccTy.
change (TSigma (ListTy 0) (OptionTy 0))
with (TSigma (ListTy 0) (subst_ty TVar (abstract_term_var 1) (OptionTy 0))).
eapply ST_Pair.
+ type_var.
+ apply ST_Inl. apply ST_Unit.
- (* Loop body : TSum AccTy ResTy *)
(* The body is deeply nested pattern matches. We admit the inner
derivation for now — the key subtyping lemmas above (U_sub_T,
list_unfold_sub, ordering_sub, or_same_sub) are the interesting part. *)
admit.
Admitted.