Fixpoint naryFunc (A : Set) (n : nat) {struct n} : Set :=
  match n with
  | O => A
  | S m => A -> naryFunc A m
  end.Fixpoint naryRel (A : Set) (n : nat) {struct n} : Type :=
  match n with
  | O => Prop
  | S m => A -> naryRel A m
  end.Record Model : Type := model
  {U : Set;
   func : forall f : Functions L, naryFunc U (arity L (inr _ f));
   rel : forall r : Relations L, naryRel U (arity L (inl _ r))}.Record Model : Type := model
  {U : Set;
   func : forall f : Functions L, naryFunc U (arity L (inr _ f));
   rel : forall r : Relations L, naryRel U (arity L (inl _ r))}.Record Model : Type := model
  {U : Set;
   func : forall f : Functions L, naryFunc U (arity L (inr _ f));
   rel : forall r : Relations L, naryRel U (arity L (inl _ r))}.Record Model : Type := model
  {U : Set;
   func : forall f : Functions L, naryFunc U (arity L (inr _ f));
   rel : forall r : Relations L, naryRel U (arity L (inl _ r))}.Record Model : Type := model
  {U : Set;
   func : forall f : Functions L, naryFunc U (arity L (inr _ f));
   rel : forall r : Relations L, naryRel U (arity L (inl _ r))}.Fixpoint interpTerm (value : nat -> U M) (t : Term L) {struct t} : 
 U M :=
  match t with
  | var v => value v
  | apply f ts => interpTerms _ (func M f) value ts
  end
 
 with interpTerms (m : nat) (f : naryFunc (U M) m) 
 (value : nat -> U M) (ts : Terms L m) {struct ts} : 
 U M :=
  match ts in (Terms _ n) return (naryFunc (U M) n -> U M) with
  | Tnil => fun f => f
  | Tcons m t ts => fun f => interpTerms m (f (interpTerm value t)) value ts
  end f.Fixpoint interpRels (m : nat) (r : naryRel (U M) m) 
 (value : nat -> U M) (ts : Terms L m) {struct ts} : Prop :=
  match ts in (Terms _ n) return (naryRel (U M) n -> Prop) with
  | Tnil => fun r => r
  | Tcons m t ts => fun r => interpRels m (r (interpTerm value t)) value ts
  end r.Definition updateValue (value : nat -> U M) (n : nat) 
  (v : U M) (x : nat) : U M :=
  match eq_nat_dec n x with
  | left _ => v
  | right _ => value x
  end.Fixpoint interpFormula (value : nat -> U M) (f : Formula L) {struct f} :
 Prop :=
  match f with
  | equal t s => interpTerm value t = interpTerm value s
  | atomic r ts => interpRels _ (rel M r) value ts
  | impH A B => interpFormula value A -> interpFormula value B
  | notH A => interpFormula value A -> False
  | forallH v A => forall x : U M, interpFormula (updateValue value v x) A
  end.

(* Specifications: *)
Lemma freeVarInterpTerm : forall (v1 v2 : nat -> U M) (t : Term L), (forall x : nat, In x (freeVarTerm L t) -> v1 x = v2 x) -> interpTerm v1 t = interpTerm v2 t.
Lemma freeVarInterpRel : forall (v1 v2 : nat -> U M) (n : nat) (ts : Terms L n) (r : naryRel (U M) n), (forall x : nat, In x (freeVarTerms L n ts) -> v1 x = v2 x) -> interpRels n r v1 ts -> interpRels n r v2 ts.
Lemma freeVarInterpFormula : forall (v1 v2 : nat -> U M) (g : Formula L), (forall x : nat, In x (freeVarFormula L g) -> v1 x = v2 x) -> interpFormula v1 g -> interpFormula v2 g.
Lemma subInterpTerm : forall (value : nat -> U M) (t : Term L) (v : nat) (s : Term L), interpTerm (updateValue value v (interpTerm value s)) t = interpTerm value (substituteTerm L t v s).
Lemma subInterpRel : forall (value : nat -> U M) (n : nat) (ts : Terms L n) (v : nat) (s : Term L) (r : naryRel (U M) n), interpRels n r (updateValue value v (interpTerm value s)) ts <-> interpRels n r value (substituteTerms L n ts v s).
Lemma subInterpFormula : forall (value : nat -> U M) (f : Formula L) (v : nat) (s : Term L), interpFormula (updateValue value v (interpTerm value s)) f <-> interpFormula value (substituteFormula L f v s).
Lemma subInterpFormula1 : forall (value : nat -> U M) (f : Formula L) (v : nat) (s : Term L), interpFormula (updateValue value v (interpTerm value s)) f -> interpFormula value (substituteFormula L f v s).
Lemma subInterpFormula2 : forall (value : nat -> U M) (f : Formula L) (v : nat) (s : Term L), interpFormula value (substituteFormula L f v s) -> interpFormula (updateValue value v (interpTerm value s)) f.