Library MetaCoq.PCUIC.PCUICReflect





Notion of reflection for Type-based properties

Inductive reflectT (A : Type) : bool Type :=
| ReflectT : A reflectT A true
| ReflectF : (A False) reflectT A false.

Lemma reflectT_reflect (A : Prop) b : reflectT A b reflect A b.

Lemma reflect_reflectT (A : Prop) b : reflect A b reflectT A b.


Class ReflectEq A := {
  eqb : A A bool ;
  eqb_spec : x y : A, reflect (x = y) (eqb x y)
}.

Instance ReflectEq_EqDec :
   A, ReflectEq A EqDec A.

Definition eq_dec_to_bool {A} `{EqDec A} x y :=
  match eq_dec x y with
  | left _true
  | right _false
  end.

Lemma EqDec_ReflectEq : A `{EqDec A}, ReflectEq A.


Definition eq_option {A} `{ReflectEq A} (u v : option A) : bool :=
  match u, v with
  | Some u, Some veqb u v
  | None, Nonetrue
  | _, _false
  end.

Instance reflect_option : {A}, ReflectEq A ReflectEq (option A) := {
  eqb := eq_option
}.

Fixpoint eq_list {A} (eqA : A A bool) (l l' : list A) : bool :=
  match l, l' with
  | a :: l, a' :: l'
    if eqA a a' then eq_list eqA l l'
    else false
  | [], []true
  | _, _false
  end.

Instance reflect_list : {A}, ReflectEq A ReflectEq (list A) := {
  eqb := eq_list eqb
}.

Instance reflect_string : ReflectEq string := {
  eqb := eq_string
}.

Instance reflect_nat : ReflectEq nat := {
  eqb_spec := Nat.eqb_spec
}.

Definition eq_level l1 l2 :=
  match l1, l2 with
  | Level.lProp, Level.lProptrue
  | Level.lSet, Level.lSettrue
  | Level.Level s1, Level.Level s2eqb s1 s2
  | Level.Var n1, Level.Var n2eqb n1 n2
  | _, _false
  end.

Instance reflect_level : ReflectEq Level.t := {
  eqb := eq_level
}.

Definition eq_prod {A B} (eqA : A A bool) (eqB : B B bool) x y :=
  let '(a1, b1) := x in
  let '(a2, b2) := y in
  if eqA a1 a2 then eqB b1 b2
  else false.

Instance reflect_prod : {A B}, ReflectEq A ReflectEq B ReflectEq (A × B) := {
  eqb := eq_prod eqb eqb
}.

Definition eq_bool b1 b2 : bool :=
  if b1 then b2 else negb b2.

Instance reflect_bool : ReflectEq bool := {
  eqb := eq_bool
}.

Definition eq_name na nb :=
  match na, nb with
  | nAnon, nAnontrue
  | nNamed a, nNamed beqb a b
  | _, _false
  end.

Instance reflect_name : ReflectEq name := {
  eqb := eq_name
}.

Definition eq_inductive ind ind' :=
  match ind, ind' with
  | mkInd m n, mkInd m' n'
    eqb m m' && eqb n n'
  end.

Instance reflect_inductive : ReflectEq inductive := {
  eqb := eq_inductive
}.

Lemma eq_inductive_refl i : eq_inductive i i.

Definition eq_def {A : Set} `{ReflectEq A} (d1 d2 : def A) : bool :=
  match d1, d2 with
  | mkdef n1 t1 b1 a1, mkdef n2 t2 b2 a2
    eqb n1 n2 && eqb t1 t2 && eqb b1 b2 && eqb a1 a2
  end.

Instance reflect_def : {A : Set} `{ReflectEq A}, ReflectEq (def A) := {
  eqb := eq_def
}.

Fixpoint eq_non_empty_list {A : Set} (eqA : A A bool) (l l' : non_empty_list A) : bool :=
  match l, l' with
  | NEL.sing a, NEL.sing a'eqA a a'
  | NEL.cons a l, NEL.cons a' l'
    eqA a a' && eq_non_empty_list eqA l l'
  | _, _false
  end.

Instance reflect_non_empty_list :
   {A : Set} `{ReflectEq A}, ReflectEq (non_empty_list A) :=
  { eqb := eq_non_empty_list eqb }.






Instance reflect_term : ReflectEq term :=
  let h := EqDec_ReflectEq term in _.

Definition eq_sig_true {A f} `{ReflectEq A} (x y : { z : A | f z = true }) : bool :=
  let '(exist x hx) := x in
  let '(exist y hy) := y in
  eqb x y.

Instance reflect_sig_true {A f} `{ReflectEq A} : ReflectEq ({ z : A | f z = true }) := {
  eqb := eq_sig_true
}.


Definition eqb_context_decl (x y : context_decl) :=
  let (na, b, ty) := x in
  let (na', b', ty') := y in
  eqb na na' && eqb b b' && eqb ty ty'.

Instance eq_ctx : ReflectEq context_decl.

Instance eqb_ctx : ReflectEq context := _.