From program_logic Require Export ghost_ownership. Module rFunctors. Inductive rFunctors := | nil : rFunctors | cons : rFunctor → rFunctors → rFunctors. Coercion singleton (F : rFunctor) : rFunctors := cons F nil. Fixpoint fold_right {A} (f : rFunctor → A → A) (a : A) (Fs : rFunctors) : A := match Fs with | nil => a | cons F Fs => f F (fold_right f a Fs) end. End rFunctors. Notation rFunctors := rFunctors.rFunctors. Delimit Scope rFunctors_scope with rFunctors. Bind Scope rFunctors_scope with rFunctors. Arguments rFunctors.cons _ _%rFunctors. Notation "[ ]" := rFunctors.nil (format "[ ]") : rFunctors_scope. Notation "[ F ]" := (rFunctors.cons F rFunctors.nil) : rFunctors_scope. Notation "[ F ; .. ; F' ]" := (rFunctors.cons F .. (rFunctors.cons F' rFunctors.nil) ..) : rFunctors_scope. Module rFunctorG. Definition nil : rFunctorG := const (constRF unitR). Definition cons (F : rFunctor) (Σ : rFunctorG) : rFunctorG := λ n, match n with O => F | S n => Σ n end. Fixpoint app (Fs : rFunctors) (Σ : rFunctorG) : rFunctorG := match Fs with | rFunctors.nil => Σ | rFunctors.cons F Fs => cons F (app Fs Σ) end. End rFunctorG. (** Cannot bind this scope with the [rFunctorG] since [rFunctorG] is a notation hiding a more complex type. *) Notation "#[ ]" := rFunctorG.nil (format "#[ ]"). Notation "#[ Fs ]" := (rFunctorG.app Fs rFunctorG.nil). Notation "#[ Fs ; .. ; Fs' ]" := (rFunctorG.app Fs .. (rFunctorG.app Fs' rFunctorG.nil) ..). (** We need another typeclass to identify the *functor* in the Σ. Basing inG on the functor breaks badly because Coq is unable to infer the correct typeclasses, it does not unfold the functor. *) Class inGF (Λ : language) (Σ : rFunctorG) (F : rFunctor) := InGF { inGF_id : gid; inGF_prf : F = Σ inGF_id; }. (* Avoid eager type class search: this line ensures that type class search is only triggered if the first two arguments of inGF do not contain evars. Since instance search for [inGF] is restrained, instances should always have [inGF] as their first argument to avoid loops. For example, the instances [authGF_inGF] and [auth_identity] otherwise create a cycle that pops up arbitrarily. *) Hint Mode inGF + + - : typeclass_instances. Lemma inGF_inG `{inGF Λ Σ F} : inG Λ Σ (F (iPreProp Λ (globalF Σ))). Proof. exists inGF_id. by rewrite -inGF_prf. Qed. Instance inGF_here {Λ Σ} (F: rFunctor) : inGF Λ (rFunctorG.cons F Σ) F. Proof. by exists 0. Qed. Instance inGF_further {Λ Σ} (F F': rFunctor) : inGF Λ Σ F → inGF Λ (rFunctorG.cons F' Σ) F. Proof. intros [i ?]. by exists (S i). Qed. (** For modules that need more than one functor, we offer a typeclass [inGFs] to demand a list of rFunctor to be available. We do *not* register any instances that go from there to [inGF], to avoid cycles. *) Class inGFs (Λ : language) (Σ : rFunctorG) (Fs : rFunctors) := InGFs : (rFunctors.fold_right (λ F T, inGF Λ Σ F * T) () Fs)%type. Instance inGFs_nil {Λ Σ} : inGFs Λ Σ []. Proof. exact tt. Qed. Instance inGFs_cons {Λ Σ} F Fs : inGF Λ Σ F → inGFs Λ Σ Fs → inGFs Λ Σ (rFunctors.cons F Fs). Proof. by split. Qed.