+ (*
+ * Here it is, what you've all been waiting for! When reading this,
+ * it might help to have the definition for "Inductive ND" (see
+ * NaturalDeduction.v) handy as a cross-reference.
+ *)
+ Definition FlatteningFunctor_fmor {Γ}{Δ}
+ : forall h c,
+ (h~~{JudgmentsL _ _ (PCF 0 Γ Δ)}~~>c) ->
+ ((obact 0 h)~~{TypesL _ _ (SystemFC Γ Δ)}~~>(obact 0 c)).
+ unfold hom; unfold ob; unfold ehom; simpl; unfold mon_i; unfold obact; intros.
+
+ induction X; simpl.
+
+ (* the proof from no hypotheses of no conclusions (nd_id0) becomes REmptyGroup *)
+ apply nd_rule; apply org_fc; simpl. apply nd_rule. apply REmptyGroup.
+
+ (* the proof from hypothesis X of conclusion X (nd_id1) becomes RVar *)
+ apply nd_rule; apply org_fc; simpl. apply nd_rule. destruct (guestJudgmentAsGArrowType h). apply RVar.
+
+ (* the proof from hypothesis X of no conclusions (nd_weak) becomes RWeak;;REmptyGroup *)
+ apply nd_rule; apply org_fc; simpl.
+ eapply nd_comp; [ idtac | apply (nd_rule (RURule _ _ _ _ (RWeak _ _))) ].
+ apply nd_rule. apply REmptyGroup.
+
+ (* the proof from hypothesis X of two identical conclusions X,,X (nd_copy) becomes RVar;;RBindingGroup;;RCont *)
+ eapply nd_comp; [ idtac | eapply nd_rule; eapply org_fc; apply (nd_rule (RURule _ _ _ _ (RCont _ _))) ].
+ eapply nd_comp; [ apply nd_llecnac | idtac ].
+ set (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ)) (mapOptionTree guestJudgmentAsGArrowType h)) as q.
+ eapply nd_comp.
+ eapply nd_prod.
+ apply q.
+ apply q.
+ apply nd_rule; eapply org_fc.
+ simpl.
+ apply nd_rule.
+ apply RBindingGroup.
+
+ (* nd_prod becomes nd_llecnac;;nd_prod;;RBindingGroup *)
+ eapply nd_comp.
+ apply (nd_llecnac ;; nd_prod IHX1 IHX2).
+ apply nd_rule; apply org_fc; simpl.
+ eapply nd_rule. apply RBindingGroup.
+
+ (* nd_comp becomes pl_subst (aka nd_cut) *)
+ eapply nd_comp.
+ apply (nd_llecnac ;; nd_prod IHX1 IHX2).
+ clear IHX1 IHX2 X1 X2.
+ apply (@nd_cut _ _ _ _ _ _ (@pl_subst _ _ _ _ (SystemFC Γ Δ))).
+
+ (* nd_cancell becomes RVar;;RuCanL *)
+ eapply nd_comp;
+ [ idtac | eapply nd_rule; apply org_fc; simpl; apply nd_rule; apply (RURule _ _ _ _ (RuCanL _ _)) ].
+ apply (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ))).
+
+ (* nd_cancelr becomes RVar;;RuCanR *)
+ eapply nd_comp;
+ [ idtac | eapply nd_rule; apply org_fc; simpl; apply nd_rule; apply (RURule _ _ _ _ (RuCanR _ _)) ].
+ apply (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ))).
+
+ (* nd_llecnac becomes RVar;;RCanL *)
+ eapply nd_comp;
+ [ idtac | eapply nd_rule; apply org_fc; simpl; apply nd_rule; apply (RURule _ _ _ _ (RCanL _ _)) ].
+ apply (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ))).
+
+ (* nd_rlecnac becomes RVar;;RCanR *)
+ eapply nd_comp;
+ [ idtac | eapply nd_rule; apply org_fc; simpl; apply nd_rule; apply (RURule _ _ _ _ (RCanR _ _)) ].
+ apply (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ))).
+
+ (* nd_assoc becomes RVar;;RAssoc *)
+ eapply nd_comp;
+ [ idtac | eapply nd_rule; apply org_fc; simpl; apply nd_rule; apply (RURule _ _ _ _ (RAssoc _ _ _ _)) ].
+ apply (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ))).
+
+ (* nd_coss becomes RVar;;RCossa *)
+ eapply nd_comp;
+ [ idtac | eapply nd_rule; apply org_fc; simpl; apply nd_rule; apply (RURule _ _ _ _ (RCossa _ _ _ _)) ].
+ apply (nd_seq_reflexive(SequentCalculus:=@pl_sc _ _ _ _ (SystemFC Γ Δ))).
+
+ (* now, the interesting stuff: the inference rules of Judgments(PCF) become GArrow-parameterized terms *)
+ refine (match r as R in OrgR B N G D H C return
+ match N with
+ | S _ => True
+ | O => if B then True
+ else ND (OrgR true 0 G D)
+ []
+ [G >> D > mapOptionTree guestJudgmentAsGArrowType H |- mapOptionTree guestJudgmentAsGArrowType C]
+ end with
+ | org_pcf n Γ Δ h c b r => _
+ | org_fc n Γ Δ h c r => _
+ | org_nest n Γ Δ h c b v q => _
+ end); destruct n; try destruct b; try apply I.
+ destruct r0.
+
+ clear r h c Γ Δ.
+ rename r0 into r; rename h0 into h; rename c0 into c; rename Γ0 into Γ; rename Δ0 into Δ.
+
+ refine (match r as R in Rule_PCF _ _ H C _ with
+ | PCF_RURule h c r => let case_RURule := tt in _
+ | PCF_RLit Σ τ => let case_RLit := tt in _
+ | PCF_RNote Σ τ l n => let case_RNote := tt in _
+ | PCF_RVar σ l=> let case_RVar := tt in _
+ | PCF_RLam Σ tx te q => let case_RLam := tt in _
+ | PCF_RApp Σ tx te p l=> let case_RApp := tt in _
+ | PCF_RLet Σ σ₁ σ₂ p l=> let case_RLet := tt in _
+ | PCF_RBindingGroup b c d e => let case_RBindingGroup := tt in _
+ | PCF_REmptyGroup => let case_REmptyGroup := tt in _
+(* | PCF_RCase T κlen κ θ l x => let case_RCase := tt in _*)
+(* | PCF_RLetRec Σ₁ τ₁ τ₂ lev => let case_RLetRec := tt in _*)
+ end ); simpl in *.
+ clear x r h c.
+ rename r0 into r; rename h0 into h; rename c0 into c.
+
+ destruct case_RURule.
+ refine (match r with
+ | RLeft a b c r => let case_RLeft := tt in _
+ | RRight a b c r => let case_RRight := tt in _
+ | RCanL a b => let case_RCanL := tt in _
+ | RCanR a b => let case_RCanR := tt in _
+ | RuCanL a b => let case_RuCanL := tt in _
+ | RuCanR a b => let case_RuCanR := tt in _
+ | RAssoc a b c d => let case_RAssoc := tt in _
+ | RCossa a b c d => let case_RCossa := tt in _
+ | RExch a b c => let case_RExch := tt in _
+ | RWeak a b => let case_RWeak := tt in _
+ | RCont a b => let case_RCont := tt in _
+ end).
+
+ destruct case_RCanL.
+ (* ga_cancell *)
+ admit.
+
+ destruct case_RCanR.
+ (* ga_cancelr *)
+ admit.
+
+ destruct case_RuCanL.
+ (* ga_uncancell *)
+ admit.
+
+ destruct case_RuCanR.
+ (* ga_uncancelr *)
+ admit.
+
+ destruct case_RAssoc.
+ (* ga_assoc *)
+ admit.
+
+ destruct case_RCossa.
+ (* ga_unassoc *)
+ admit.
+
+ destruct case_RLeft.
+ (* ga_second *)
+ admit.
+
+ destruct case_RRight.
+ (* ga_first *)
+ admit.
+
+ destruct case_RExch.
+ (* ga_swap *)
+ admit.
+
+ destruct case_RWeak.
+ (* ga_drop *)
+ admit.
+
+ destruct case_RCont.
+ (* ga_copy *)
+ admit.
+
+ destruct case_RLit.
+ (* ga_literal *)
+ admit.
+
+ (* hey cool, I figured out how to pass CoreNote's through... *)
+ destruct case_RNote.
+ apply nd_rule.
+ apply org_fc.
+ eapply nd_comp.
+ eapply nd_rule.
+ apply RVar.
+ apply nd_rule.
+ apply RNote.
+ apply n.
+
+ destruct case_RVar.
+ (* ga_id *)
+ admit.
+
+ destruct case_RLam.
+ (* ga_curry, but try to avoid this someday in the future if the argument type isn't a function *)
+ admit.
+
+ destruct case_RApp.
+ (* ga_apply *)
+ admit.
+
+ destruct case_RLet.
+ (* ga_comp! perhaps this means the ga_curry avoidance can be done by turning lambdas into lets? *)
+ admit.
+
+ destruct case_RBindingGroup.
+ (* ga_first+ga_second; technically this assumes a specific evaluation order, which is bad *)
+ admit.
+
+ destruct case_REmptyGroup.
+ (* ga_id u *)
+ admit.
+ Defined.
+
+ Instance FlatteningFunctor {n}{Γ}{Δ} : Functor (JudgmentsL _ _ (PCF n Γ Δ)) (TypesL _ _ (SystemFCa n Γ Δ)) obact :=
+ { fmor := FlatteningFunctor_fmor }.
+ unfold hom; unfold ob; unfold ehom; intros; simpl.
+
+
+ Definition productifyType {Γ} (lt:Tree ??(LeveledHaskType Γ ★)) : LeveledHaskType Γ ★.
+ admit.
+ Defined.
+
+ Definition exponent {Γ} : LeveledHaskType Γ ★ -> LeveledHaskType Γ ★ -> LeveledHaskType Γ ★.
+ admit.
+ Defined.
+
+ Definition brakify {Γ}(Σ τ:Tree ??(LeveledHaskType Γ ★)) := exponent (productifyType Σ) (productifyType τ).
+
+ Definition brakifyJudg (j:Judg) : Judg :=
+ match j with
+ Γ > Δ > Σ |- τ =>
+ Γ > Δ > [] |- [brakify Σ τ]
+ end.
+
+ Definition brakifyUJudg (j:Judg) : Judg :=
+ match j with
+ Γ > Δ > Σ |- τ =>
+ Γ > Δ > [] |- [brakify Σ τ]
+ end.
+ *)
+
+ End RuleSystemFC.
+
+ Context (ndr_pcf :forall n Γ Δ, @ND_Relation _ (@RulePCF Γ Δ n)).
+
+
+ Instance PCF n Γ Δ : @ProgrammingLanguage _ _ (mkJudg Γ Δ) (@RulePCF Γ Δ n) :=
+ { pl_eqv := _
+ ; pl_tsr := _ (*@TreeStructuralRules Judg Rule T sequent*)
+ ; pl_sc := _ (*@SequentCalculus Judg Rule _ sequent*)
+ ; pl_subst := _ (*@CutRule Judg Rule _ sequent pl_eqv pl_sc*)
+ ; pl_sequent_join := _ (*@SequentExpansion Judg Rule T sequent pl_eqv pl_sc pl_subst*)
+ }.
+ Admitted.
+
+ Inductive RuleX : nat -> Tree ??Judg -> Tree ??Judg -> Type :=
+ | x_flat : forall n h c (r:Rule h c), Rule_Flat r -> RuleX n h c
+ | x_nest : forall n Γ Δ h c, ND (@RulePCF Γ Δ n) h c ->
+ RuleX (S n) (mapOptionTree brakifyJudg h) (mapOptionTree brakifyJudg c).