From c1ed805c2b93c3c491d89ca70e3e7ca0f5d7ea8a Mon Sep 17 00:00:00 2001 From: jihgfee <jihgfee@gmail.com> Date: Thu, 17 Sep 2020 14:07:20 +0200 Subject: [PATCH] Added typing example for uncheckable mapper --- _CoqProject | 1 + theories/logrel/examples/mapper_list.v | 496 +++++++++++++++++++++++++ 2 files changed, 497 insertions(+) create mode 100644 theories/logrel/examples/mapper_list.v diff --git a/_CoqProject b/_CoqProject index c966745..24777b0 100644 --- a/_CoqProject +++ b/_CoqProject @@ -44,3 +44,4 @@ theories/logrel/examples/pair.v theories/logrel/examples/rec_subtyping.v theories/logrel/examples/choice_subtyping.v theories/logrel/examples/mapper.v +theories/logrel/examples/mapper_list.v \ No newline at end of file diff --git a/theories/logrel/examples/mapper_list.v b/theories/logrel/examples/mapper_list.v new file mode 100644 index 0000000..3175411 --- /dev/null +++ b/theories/logrel/examples/mapper_list.v @@ -0,0 +1,496 @@ +From actris.channel Require Import proofmode proto channel. +From actris.logrel Require Import session_types subtyping_rules + term_typing_judgment term_typing_rules session_typing_rules + environments telescopes napp. +From actris.utils Require Import llist. +From actris.logrel.lib Require Import par_start. +From iris.proofmode Require Import tactics. + +Definition mapper_service_aux : expr := λ: "f" "c", + (rec: "go" "f" "c":= + (branch [1%Z;2%Z]) "c" + (λ: "c", let: "v" := recv "c" in + send "c" ("f" "v");; "go" "f" "c") + (λ: "c", #())) "f" "c". + +Definition mapper_service : expr := + λ: "c", + let: "f" := recv "c" in + mapper_service_aux "f" "c". + +Definition send_all : val := + rec: "go" "c" "xs" := + if: lisnil "xs" then #() else + send "c" #1;; send "c" (lpop "xs");; "go" "c" "xs". + +Definition recv_all : val := + rec: "go" "c" "ys" "n" := + if: "n" = #0 then #() else + let: "x" := recv "c" in + "go" "c" "ys" ("n"-#1);; lcons "x" "ys". + +Definition mapper_client : expr := + (λ: "f" "xs" "c", + send "c" "f";; + let: "n" := llength "xs" in + send_all "c" "xs";; recv_all "c" "xs" "n";; send "c" #2%Z;; "xs")%E. + +Definition mapper_prog : expr := + (λ: "f" "xs", + par_start (mapper_service) (mapper_client "f" "xs"))%E. + +Section mapper_example. + Context `{heapG Σ, chanG Σ}. + + Definition mapper_type_rec_service_aux (A : ltty Σ) (B : ltty Σ) (rec : lsty Σ) + : lsty Σ := + lty_branch + (<[1%Z := (<??> TY A; <!!> TY B ; rec)%lty]> + (<[2%Z := END%lty]>∅)). + Instance mapper_type_rec_service_contractive A B : + Contractive (mapper_type_rec_service_aux A B). + Proof. solve_proto_contractive. Qed. + Definition mapper_type_rec_service A B : lsty Σ := + lty_rec (mapper_type_rec_service_aux A B). + + Lemma ltyped_mapper_aux_service Γ A B : + ⊢ Γ ⊨ mapper_service_aux : (A → B) ⊸ lty_chan (mapper_type_rec_service A B) ⊸ + () ⫤ Γ. + Proof. + iApply (ltyped_lam []). + iApply (ltyped_lam [EnvItem "f" _]). + iApply ltyped_app; [ by iApply ltyped_var | ]. + iApply ltyped_app; [ by iApply ltyped_var | ]. + iApply (ltyped_subsumption _ _ _ _ _ _ + ((A → B) → lty_chan (mapper_type_rec_service A B) ⊸ ())%lty); + [ | iApply lty_le_copy_elim | iApply env_le_refl | ]. + { iApply env_le_cons. iApply lty_le_copy_inv_elim. iApply env_le_refl. } + iApply ltyped_post_nil. + iApply (ltyped_rec []). + iApply (ltyped_lam [EnvItem "go" _; EnvItem "f" _]). + iApply ltyped_post_nil. + iApply ltyped_app. + { iApply (ltyped_lam []). iApply ltyped_post_nil. iApply ltyped_unit. } + iApply ltyped_app. + { + simpl. rewrite !(Permutation_swap (EnvItem "f" _)) + !(Permutation_swap (EnvItem "go" _)). + iApply (ltyped_lam [EnvItem "go" _; EnvItem "f" _]). + iApply ltyped_post_nil. + iApply ltyped_let; [ by iApply ltyped_recv | ]. + iApply ltyped_seq. + { iApply (ltyped_send _ + [EnvItem "f" _; EnvItem "v" _; EnvItem "c" _; EnvItem "go" _]); + [ done | ]. + iApply ltyped_app_copy; [ by iApply ltyped_var | ]=> /=. + rewrite !(Permutation_swap (EnvItem "f" _)). + by iApply ltyped_var. } + simpl. rewrite !(Permutation_swap (EnvItem "f" _)). + iApply ltyped_subsumption; [ | iApply lty_le_refl | iApply env_le_refl | ]. + { iApply env_le_cons; [ | iApply env_le_refl ]. + iApply lty_le_copy_inv_elim_copyable. iApply lty_copyable_arr_copy. } + iApply ltyped_app; [ by iApply ltyped_var | ]. + iApply ltyped_app; [ by iApply ltyped_var | ]. + simpl. rewrite !(Permutation_swap (EnvItem "go" _)). + iApply ltyped_subsumption; [ iApply env_le_refl | | iApply env_le_refl | ]. + { iApply lty_le_copy_elim. } + by iApply ltyped_var. } + iApply ltyped_app; [ by iApply ltyped_var | ]. + iApply ltyped_subsumption; [ iApply env_le_refl | | iApply env_le_refl | ]. + { iApply lty_le_arr; [ | iApply lty_le_refl ]. iApply lty_le_chan. + iApply lty_le_l; [ iApply lty_le_rec_unfold | iApply lty_le_refl ]. } + iApply ltyped_branch. intros x. rewrite -elem_of_dom. set_solver. + Qed. + + Definition mapper_type_service : lsty Σ := + <?? A B> TY A → B ; mapper_type_rec_service A B. + + Lemma ltyped_mapper_service Γ : + ⊢ Γ ⊨ mapper_service : lty_chan (mapper_type_service) ⊸ () ⫤ Γ. + Proof. + iApply (ltyped_lam []). + iApply ltyped_post_nil. + iApply ltyped_recv_texist; [ done | apply _ | ]. + iIntros (Ys). + iApply ltyped_app; [ by iApply ltyped_var | ]. + iApply ltyped_app; [ by iApply ltyped_var | ]. + pose proof (ltys_S_inv Ys) as [A [Ks HYs]]. + pose proof (ltys_S_inv Ks) as [B [Ks' HKs]]. + pose proof (ltys_O_inv Ks') as HKs'. + rewrite HYs HKs HKs' /=. + iApply (ltyped_subsumption _ []); + [ iApply env_le_nil | iApply lty_le_refl | iApply env_le_refl | ]. + iApply ltyped_mapper_aux_service. + Qed. + + Definition mapper_type_rec_client_aux + (A : ltty Σ) (B : ltty Σ) (rec : lsty Σ) : lsty Σ := + lty_select (<[1%Z := (<!!> TY A; <??> TY B ; rec)%lty]> + (<[2%Z := END%lty]>∅)). + Instance mapper_type_rec_client_contractive A B : + Contractive (mapper_type_rec_client_aux A B). + Proof. solve_proto_contractive. Qed. + Definition mapper_type_rec_client A B : lsty Σ := + lty_rec (mapper_type_rec_client_aux A B). + Global Instance mapper_type_rec_client_unfold A B : + ProtoUnfold (lsty_car (mapper_type_rec_client A B)) + (lsty_car (mapper_type_rec_client_aux A B + (mapper_type_rec_client A B))). + Proof. apply proto_unfold_eq, + (fixpoint_unfold (mapper_type_rec_client_aux A B)). Qed. + + Definition mapper_type_client : lsty Σ := + <!! A B> TY A → B ; mapper_type_rec_client A B. + + Definition lty_list_aux (A : ltty Σ) (X : ltty Σ) : ltty Σ := + (() + (A * ref_uniq X))%lty. + Instance lty_list_aux_contractive A : + Contractive (lty_list_aux A). + Proof. solve_proto_contractive. Qed. + Definition lty_list (A : ltty Σ) : ltty Σ := lty_rec (lty_list_aux A). + + Notation "'list' A" := (lty_list A) (at level 10) : lty_scope. + + Definition list_pred (A : ltty Σ) : val → val → iProp Σ := + (λ v w : val, ⌜v = w⌠∗ ltty_car A v)%I. + + Lemma llength_spec A (l : loc) : + ⊢ {{{ ltty_car (ref_uniq (list A)) #l }}} llength #l + {{{ xs (n:Z), RET #n; ⌜Z.of_nat (length xs) = n⌠∗ + llist (λ v w , ⌜v = w⌠∗ ltty_car A v) l xs }}}. + Proof. + iIntros "!>" (Φ) "Hl HΦ". + iLöb as "IH" forall (l Φ). + iDestruct "Hl" as (ltmp l' [=]) "[Hl Hl']"; rewrite -H2. + wp_lam. + rewrite {2}/lty_list /lty_rec /lty_list_aux fixpoint_unfold. + iDestruct "Hl'" as "[Hl' | Hl']". + - iDestruct "Hl'" as (xs ->) "Hl'". + wp_load. wp_pures. + iAssert (llist (list_pred A) l [])%I with "[Hl Hl']" as "Hl". + { rewrite /llist. iDestruct "Hl'" as %->. iApply "Hl". } + iApply "HΦ". eauto with iFrame. + - iDestruct "Hl'" as (xs ->) "Hl'". + wp_load. wp_pures. + iDestruct "Hl'" as (x vl' ->) "[HA Hl']". + iDestruct "Hl'" as (l' xs ->) "[Hl' Hl'']". + wp_apply ("IH" with "[Hl' Hl'']"). + { iExists _, _. iFrame "Hl' Hl''". done. } + iIntros (ys n) "[<- H]". + iAssert (llist (list_pred A) l (x :: ys))%I with "[Hl HA H]" as "Hl". + { iExists x, l'. eauto with iFrame. } + wp_pures. iApply "HΦ". iFrame "Hl". by rewrite (Nat2Z.inj_add 1). + Qed. + + Definition send_type (A : ltty Σ) : lsty Σ := + (lty_select (<[1%Z := <!!> TY A ; END ]>∅))%lty. + Definition recv_type (B : ltty Σ) : lsty Σ := + (<??> TY B ; END)%lty. + + Lemma mapper_rec_client_unfold_app A B : + ⊢ mapper_type_rec_client A B <: + (send_type A <++> (recv_type B <++> mapper_type_rec_client A B))%lty. + Proof. + rewrite {1}/mapper_type_rec_client /lty_rec fixpoint_unfold. + replace (fixpoint (mapper_type_rec_client_aux A B)) with + (mapper_type_rec_client A B) by eauto. + rewrite /mapper_type_rec_client_aux. + iApply lty_le_trans. + { iApply lty_le_select_subseteq. + apply insert_mono, insert_subseteq=> //. } + rewrite /send_type /recv_type. + iPoseProof (lty_le_app_select) as "[_ Hle]". + iApply (lty_le_trans); last by iApply "Hle". + rewrite fmap_insert fmap_empty. + rewrite lty_app_send lty_app_end_l. + rewrite lty_app_recv lty_app_end_l. + iApply lty_le_refl. + Qed. + + Lemma recv_send_swap A B : + ⊢ (recv_type B <++> send_type A <: send_type A <++> recv_type B)%lty. + Proof. + iApply lty_le_trans. + rewrite lty_app_recv lty_app_end_l. + iApply lty_le_swap_recv_select. rewrite fmap_insert fmap_empty. + iPoseProof (lty_le_app_select) as "[_ Hle]". + iApply (lty_le_trans); last by iApply "Hle". + rewrite fmap_insert fmap_empty. + iApply lty_le_select. + iApply big_sepM2_insert=> //. + iSplit=> //. + rewrite lty_app_send lty_app_end_l. + iApply lty_le_swap_recv_send. + Qed. + + Lemma mapper_type_rec_client_unfold_app_n A B n : + ⊢ mapper_type_rec_client A B <: + lty_napp (send_type A) n <++> (lty_napp (recv_type B) n <++> + mapper_type_rec_client A B). + Proof. + iInduction n as [|n] "IH"; simpl; [ | ]. + { rewrite /send_type /recv_type /=. + do 2 rewrite lty_app_end_l. iApply lty_le_refl. } + rewrite -lty_napp_flip -lty_napp_flip. + iEval (rewrite -assoc). + iApply lty_le_trans; last first. + { iApply lty_le_app; [ iApply lty_le_refl | ]. + iEval (rewrite -assoc assoc). + iApply lty_le_app; [ | iApply lty_le_refl ]. + iApply napp_swap. iApply recv_send_swap. } + iEval (rewrite -assoc). + iApply (lty_le_trans with "IH"). + iApply lty_le_app; [ iApply lty_le_refl | ]. + iApply lty_le_app; [ iApply lty_le_refl | ]. + iApply mapper_rec_client_unfold_app. + Qed. + + Lemma recv_send_swap_n A B n : + ⊢ (lty_napp (recv_type B) n <++> mapper_type_rec_client A B) <: + (send_type A <++> + (lty_napp (recv_type B) (S n) <++> mapper_type_rec_client A B)). + Proof. + iApply lty_le_trans. + { iApply lty_le_app; + [ iApply lty_le_refl | iApply mapper_rec_client_unfold_app ]. } + iEval (rewrite assoc). + iApply lty_le_trans. + { iApply lty_le_app; [ | iApply lty_le_refl ]. + iApply napp_swap. iApply recv_send_swap. } + iEval (rewrite -assoc (assoc _ (lty_napp _ _))). + rewrite -lty_napp_S_r. + iApply lty_le_refl. + Qed. + + Lemma send_all_spec_upfront A c l xs ty : + {{{ llist (list_pred A) l xs ∗ + c ↣ lsty_car (lty_napp (send_type A) (length xs) <++> ty) }}} + send_all c #l + {{{ RET #(); llist (list_pred A) l [] ∗ c ↣ lsty_car ty }}}. + Proof. + iIntros (Φ) "[Hl Hc] HΦ". + iInduction xs as [|x xs] "IH". + { wp_lam. wp_apply (lisnil_spec with "Hl"); iIntros "Hl"; wp_pures. + iApply "HΦ". iFrame. } + wp_lam. wp_apply (lisnil_spec with "Hl"); iIntros "Hl". + wp_send with "[]"; first by eauto. + rewrite lookup_total_insert. + wp_apply (lpop_spec with "Hl"); iIntros (v) "[HIx Hl]". + wp_send with "[HIx]". + { iDestruct "HIx" as (->) "$HIx". } + wp_apply ("IH" with "Hl Hc"). + done. + Qed. + + Lemma send_all_spec_aux A B c l xs n : + {{{ llist (list_pred A) l xs ∗ + c ↣ lsty_car (lty_napp (recv_type B) n <++> (mapper_type_rec_client A B)) }}} + send_all c #l + {{{ RET #(); llist (list_pred A) l [] ∗ + c ↣ lsty_car (lty_napp (recv_type B) (length xs + n) <++> + (mapper_type_rec_client A B)) }}}. + Proof. + iIntros (Φ) "[Hl Hc] HΦ". + iInduction xs as [|x xs] "IH" forall (n). + { wp_lam. wp_apply (lisnil_spec with "Hl"); iIntros "Hl"; wp_pures. + iApply "HΦ". iFrame. } + wp_lam. wp_apply (lisnil_spec with "Hl"); iIntros "Hl". + simpl. + iDestruct (iProto_mapsto_le c with "Hc []") as "Hc". + { iApply recv_send_swap_n. } + wp_send with "[]"; first by eauto. + rewrite lookup_total_insert. + wp_apply (lpop_spec with "Hl"); iIntros (v) "[HIx Hl]". + wp_send with "[HIx]". + { iDestruct "HIx" as (->) "$HIx". } + wp_apply ("IH" $!(S n) with "Hl Hc"). + by rewrite Nat.add_succ_r. + Qed. + + Lemma send_all_spec_ad_hoc A B c l xs : + {{{ llist (list_pred A) l xs ∗ + c ↣ lsty_car (mapper_type_rec_client A B) }}} + send_all c #l + {{{ RET #(); llist (list_pred A) l [] ∗ + c ↣ lsty_car (lty_napp (recv_type B) (length xs) + <++> (mapper_type_rec_client A B)) }}}. + Proof. + iIntros (Φ) "[Hl Hc] HΦ". + iApply (send_all_spec_aux _ _ _ _ _ 0 with "[$Hl Hc]"). + { simpl. by rewrite lty_app_end_l. } + iIntros "!> [Hl Hc]". iApply "HΦ". + rewrite -(plus_n_O (length xs)). iFrame. + Qed. + + Lemma recv_all_spec B c ty l n : + {{{ llist (list_pred B) l [] ∗ + c ↣ lsty_car (lty_napp (recv_type B) n <++> ty) }}} + recv_all c #l #n + {{{ ys, RET #(); ⌜n = length ys⌠∗ + llist (list_pred B) l ys ∗ c ↣ lsty_car ty }}}. + Proof. + iIntros (Φ) "[Hl Hc] HΦ". + iLöb as "IH" forall (n Φ). + destruct n. + { wp_lam. wp_pures. iApply "HΦ". by iFrame. } + wp_lam. wp_recv (w) as "Hw". wp_pures. + rewrite Nat2Z.inj_succ. + replace (Z.succ (Z.of_nat (n)) - 1)%Z with (Z.of_nat (n)) by lia. + wp_apply ("IH" with "Hl Hc"). + iIntros (ys) "(% & Hl & Hc)". + wp_apply (lcons_spec with "[$Hl $Hw//]"). + iIntros "Hl". iApply "HΦ". iFrame. + iPureIntro. by rewrite H1. + Qed. + + Lemma ltyped_mapper_client_ad_hoc Γ (A B : ltty Σ) : + ⊢ Γ ⊨ mapper_client : (A → B) ⊸ + ref_uniq (lty_list A) ⊸ + chan mapper_type_client ⊸ + ref_uniq (lty_list B). + Proof. + iApply (ltyped_lam []). + iApply (ltyped_lam [EnvItem "f" _]). + iApply (ltyped_lam [EnvItem "xs" _; EnvItem "f" _]). + iIntros (vs) "!> HΓ /=". + rewrite (lookup_delete_ne _ "n" "c")=> //. + rewrite (lookup_delete_ne _ "n" "xs")=> //. + rewrite lookup_delete=> //. + iDestruct (env_ltyped_cons _ _ "c" with "HΓ") as (vc ->) "[Hc HΓ]". + iDestruct (env_ltyped_cons _ _ "xs" with "HΓ") as (vl ->) "[Hl HΓ]". + iDestruct (env_ltyped_cons _ _ "f" with "HΓ") as (vf ->) "[Hf HΓ]". + wp_send with "[Hf//]". + iDestruct "Hl" as (l' v ->) "[Hl Hv]". + wp_apply (llength_spec with "[Hl Hv]"). + { iExists l', v. eauto with iFrame. } + iIntros (xs n) "[<- Hl]". + wp_pures. + wp_apply (send_all_spec_ad_hoc with "[$Hl $Hc]"). + iIntros "[Hl Hc]". + wp_apply (recv_all_spec with "[Hl $Hc //]"). + iIntros (ys). iDestruct 1 as (Hlen) "[Hl Hc]". + rewrite /mapper_type_rec_client /lty_rec fixpoint_unfold. + wp_send with "[]"; first by eauto. + wp_pures. + iFrame. + rewrite /lty_list. + iRevert (Hlen). + iInduction ys as [|y ys] "IH" forall (l' xs); iIntros (Hlen). + - iExists l', NONEV. rewrite /llist. iFrame "Hl". + iSplit=> //. + rewrite /lty_rec. rewrite (fixpoint_unfold (lty_list_aux B)). + iLeft. eauto. + - iDestruct "Hl" as (vb l'') "[[-> HB] [Hl' Hrec]]". + iExists l', _. + iFrame "Hl'". + iSplit=> //. + rewrite /lty_rec. + rewrite {2}(fixpoint_unfold (lty_list_aux B)). + iRight. iExists _. iSplit=> //. + iExists _, _. + iSplit=> //. + iFrame "HB". by iApply ("IH" with "Hrec Hc"). + Qed. + + Lemma ltyped_mapper_client_upfront Γ (A B : ltty Σ) : + ⊢ Γ ⊨ mapper_client : (A → B) ⊸ + ref_uniq (lty_list A) ⊸ + chan mapper_type_client ⊸ + ref_uniq (lty_list B). + Proof. + iApply (ltyped_lam []). + iApply (ltyped_lam [EnvItem "f" _]). + iApply (ltyped_lam [EnvItem "xs" _; EnvItem "f" _]). + iIntros (vs) "!> HΓ /=". + rewrite (lookup_delete_ne _ "n" "c")=> //. + rewrite (lookup_delete_ne _ "n" "xs")=> //. + rewrite (lookup_delete)=> //. + iDestruct (env_ltyped_cons _ _ "c" with "HΓ") as (vc ->) "[Hc HΓ]". + iDestruct (env_ltyped_cons _ _ "xs" with "HΓ") as (vl ->) "[Hl HΓ]". + iDestruct (env_ltyped_cons _ _ "f" with "HΓ") as (vf ->) "[Hf HΓ]". + wp_send with "[Hf//]". + iDestruct "Hl" as (l' v ->) "[Hl Hv]". + wp_apply (llength_spec with "[Hl Hv]"). + { iExists l', v. eauto with iFrame. } + iIntros (xs n) "[<- Hl]". + wp_pures. + iDestruct (iProto_mapsto_le vc with "Hc []") as "Hc". + { iApply (mapper_type_rec_client_unfold_app_n A B (length xs)). } + wp_apply (send_all_spec_upfront with "[$Hl $Hc]"). + iIntros "[Hl Hc]". + wp_apply (recv_all_spec with "[Hl $Hc //]"). + iIntros (ys). iDestruct 1 as (Hlen) "[Hl Hc]". + rewrite /mapper_type_rec_client /lty_rec fixpoint_unfold. + wp_send with "[]"; first by eauto. + wp_pures. + iFrame. + rewrite /lty_list. + iRevert (Hlen). + iInduction ys as [|y ys] "IH" forall (l' xs); iIntros (Hlen). + - iExists l', NONEV. rewrite /llist. iFrame "Hl". + iSplit=> //. + rewrite /lty_rec. rewrite (fixpoint_unfold (lty_list_aux B)). + iLeft. eauto. + - iDestruct "Hl" as (vb l'') "[[-> HB] [Hl' Hrec]]". + iExists l', _. + iFrame "Hl'". + iSplit=> //. + rewrite /lty_rec {2}(fixpoint_unfold (lty_list_aux B)). + iRight. iExists _. iSplit=> //. + iExists _, _. + iSplit=> //. + iFrame "HB". by iApply ("IH" with "Hrec Hc"). + Qed. + + Lemma lty_le_mapper_type_client_dual : + ⊢ lty_dual mapper_type_service <: mapper_type_client. + Proof. + rewrite /mapper_type_client /mapper_type_service. + iApply lty_le_l; [ iApply lty_le_dual_recv_exist | ]=> /=. + iIntros (A B). iExists A,B. iModIntro. + iLöb as "IH". + iApply lty_le_r; [ | iApply lty_bi_le_sym; iApply lty_le_rec_unfold ]. + iApply lty_le_dual_l. + iApply lty_le_r; [ | iApply lty_bi_le_sym; iApply lty_le_rec_unfold ]. + iApply lty_le_l; [ iApply lty_le_dual_select | ]. + iApply lty_le_branch. rewrite fmap_insert fmap_insert fmap_empty. + iApply big_sepM2_insert=> //. + iSplit. + - iApply lty_le_l; [ iApply lty_le_dual_send | ]. + iApply lty_le_recv; [ iApply lty_le_refl | ]. + iApply lty_le_l; [ iApply lty_le_dual_recv | ]. + iApply lty_le_send; [ iApply lty_le_refl | ]. + iIntros "!>!>!>". iApply lty_le_dual_l. iApply "IH". + - iApply big_sepM2_insert=> //. + iSplit=> //. iApply lty_le_l; [ iApply lty_le_dual_end | iApply lty_le_refl ]. + Qed. + + Section with_spawn. + Context `{!spawnG Σ}. + + Lemma ltyped_mapper_prog A B e1 e2 Γ Γ' Γ'' : + (Γ ⊨ e2 : ref_uniq (lty_list A) ⫤ Γ') -∗ + (Γ' ⊨ e1 : (A → B) ⫤ Γ'') -∗ + Γ ⊨ par_start (mapper_service) (mapper_client e1 e2) : + (() * (ref_uniq (lty_list B))) ⫤ Γ''. + Proof. + iIntros "He2 He1". + iApply (ltyped_app with "[He2 He1]"). + { iApply (ltyped_app with "He2"). + iApply (ltyped_app with "He1"). + iApply ltyped_mapper_client_ad_hoc. } + iApply ltyped_app. + { iApply ltyped_mapper_service. } + iApply ltyped_subsumption; + [ iApply env_le_refl | | iApply env_le_refl | ]. + { iApply lty_le_arr; [ iApply lty_le_refl | ]. + iApply lty_le_arr; [ | iApply lty_le_refl ]. + iApply lty_le_arr; [ | iApply lty_le_refl ]. + iApply lty_le_chan. + iApply lty_le_mapper_type_client_dual. } + iApply ltyped_par_start. + Qed. + + End with_spawn. + +End mapper_example. -- GitLab