Built with Alectryon, running Coq+SerAPI v8.19.0+0.19.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
(** * Bar induction *)
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Require Import Truncations.Core.Require Import Spaces.Nat.Core.Require Import Spaces.NatSeq.Core.Require Import Spaces.List.Core Spaces.List.Theory.Require Import BoundedSearch.LocalOpen Scope nat_scope.LocalOpen Scope type_scope.LocalOpen Scope list_scope.(** ** The basic definitions *)(** A family [B] on a type of lists is a bar if every infinite sequence restricts to a finite sequence satisfying [B]. *)DefinitionIsBar {A : Type} (B : list A -> Type)
:= forall (s : nat -> A), {n : nat & B (list_restrict s n)}.(** A family [B] is a uniform bar if it is a bar such that there is an upper bound for the lengths of the restrictions needed to satisfy the bar condition. *)DefinitionIsUniformBar {A : Type} (B : list A -> Type)
:= {M : nat & forall (s : nat -> A),
{n : nat & (n <= M) * B (list_restrict s n)}}.(** A family [B] on a type of finite sequences is inductive if, for every list [l], if the concatenation of [l] with any term satisfies [B], then the list satisfies [B]. *)DefinitionIsInductive {A : Type} (B : list A -> Type)
:= forall (l : list A), (forall (a : A), B (l ++ [a])) -> B l.(** A family [B] on a type of finite sequences is monotone if for every list satisfying [B], the concatenation with any other list still satisfies [B]. Equivalently, we can just check the concatenations with lists of length one. *)DefinitionIsMonotone {A : Type} (B : list A -> Type)
:= forall (l1l2 : list A), B l1 -> B (l1 ++ l2).DefinitionIsMonotoneSingleton {A : Type} (B : list A -> Type)
:= forall (l : list A) (a : A), B l -> B (l ++ [a]).
A: Type B: list A -> Type mon: IsMonotoneSingleton B
IsMonotone B
A: Type B: list A -> Type mon: IsMonotoneSingleton B
IsMonotone B
A: Type B: list A -> Type mon: IsMonotoneSingleton B l1: list A
B l1 -> B (l1 ++ nil)
A: Type B: list A -> Type mon: IsMonotoneSingleton B l1: list A a: A l2: list A IHl2: foralll1 : list A, B l1 -> B (l1 ++ l2)
B l1 -> B (l1 ++ a :: l2)
A: Type B: list A -> Type mon: IsMonotoneSingleton B l1: list A
B l1 -> B (l1 ++ nil)
byrewrite app_nil.
A: Type B: list A -> Type mon: IsMonotoneSingleton B l1: list A a: A l2: list A IHl2: foralll1 : list A, B l1 -> B (l1 ++ l2)
B l1 -> B (l1 ++ a :: l2)
A: Type B: list A -> Type mon: IsMonotoneSingleton B l1: list A a: A l2: list A IHl2: foralll1 : list A, B l1 -> B (l1 ++ l2) h: B l1
B (l1 ++ a :: l2)
A: Type B: list A -> Type mon: IsMonotoneSingleton B l1: list A a: A l2: list A IHl2: foralll1 : list A, B l1 -> B (l1 ++ l2) h: B l1
B ((l1 ++ [a]) ++ l2)
apply IHl2, mon, h.Defined.(** We state three forms of bar induction: (full) bar induction, monotone bar induction and decidable bar induction. *)DefinitionDecidableBarInduction (A : Type) :=
forall (B : list A -> Type)
(dec : forall (l : list A), Decidable (B l))
(ind : IsInductive B)
(bar : IsBar B),
B nil.DefinitionMonotoneBarInduction (A : Type) :=
forall (B : list A -> Type)
(mon : IsMonotone B)
(ind : IsInductive B)
(bar : IsBar B),
B nil.DefinitionBarInduction (A : Type) :=
forall (B : list A -> Type)
(ind : IsInductive B)
(bar : IsBar B),
B nil.(** The three bar induction principles can be more generally stated for two families. It's clear that the two-family versions imply the one-family versions. We show the reverse implications for full bar induction and monotone bar induction. We do not know if the definitions are equivalent in the decidable case yet. *)DefinitionDecidableBarInduction' (A : Type) :=
forall (BC : list A -> Type)
(sub : foralll : list A, C l -> B l)
(dC : forall (l : list A), Decidable (C l))
(ind : IsInductive B)
(bar : IsBar C),
B nil.DefinitionMonotoneBarInduction' (A : Type) :=
forall (BC : list A -> Type)
(sub : foralll : list A, C l -> B l)
(monC : IsMonotone C)
(indB : IsInductive B)
(barC : IsBar C),
B nil.DefinitionBarInduction' (A : Type) :=
forall (BC : list A -> Type)
(sub : foralll : list A, C l -> B l)
(indB : IsInductive B)
(barC : IsBar C),
B nil.Definitionbarinduction'_barinduction (A : Type) (BI : BarInduction A)
: BarInduction' A
:= funBCsubindBbarC => BI B indB (funs => ((barC s).1; sub _ (barC s).2)).
A: Type MBI: MonotoneBarInduction A
MonotoneBarInduction' A
A: Type MBI: MonotoneBarInduction A
MonotoneBarInduction' A
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C
B nil
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
B nil
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
IsMonotone P
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
IsInductive P
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
IsBar P
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
IsMonotone P
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type u, v: list A H: P u w: list A
B ((u ++ v) ++ w)
byrewrite <- app_assoc.
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
IsInductive P
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A H: foralla : A, P (l1 ++ [a])
B (l1 ++ nil)
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A H: foralla : A, P (l1 ++ [a]) a: A l2: list A
B (l1 ++ a :: l2)
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A H: foralla : A, P (l1 ++ [a])
B (l1 ++ nil)
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A H: foralla : A, P (l1 ++ [a])
foralla : A, B ((l1 ++ nil) ++ [a])
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A H: foralla : A, P (l1 ++ [a]) a: A
B ((l1 ++ nil) ++ [a])
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A a: A H: B ((l1 ++ [a]) ++ nil)
B ((l1 ++ nil) ++ [a])
byrewrite app_nil in *.
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A H: foralla : A, P (l1 ++ [a]) a: A l2: list A
B (l1 ++ a :: l2)
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type l1: list A a: A l2: list A H: B ((l1 ++ [a]) ++ l2)
B (l1 ++ a :: l2)
byrewrite <- app_assoc in H.
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type
IsBar P
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type s: nat -> A
{n : nat & P (list_restrict s n)}
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type s: nat -> A
P (list_restrict s (barC s).1)
A: Type MBI: MonotoneBarInduction A B, C: list A -> Type sub: foralll : list A, C l -> B l monC: IsMonotone C indB: IsInductive B barC: IsBar C P:= funv : list A => forallw : list A, B (v ++ w): list A -> Type s: nat -> A w: list A
B (list_restrict s (barC s).1 ++ w)
apply sub, monC, barC.Defined.(** Since decidable bar induction uses decidable predicates, we can state a logically equivalent form based on families of decidable propositions. This form has the advantage of being a proposition. *)DefinitionHPropDecidableBarInduction (A : Type) :=
forall (B : list A -> Type)
(prop : forall (l : list A), IsHProp (B l))
(dec : forall (l : list A), Decidable (B l))
(ind : IsInductive B)
(bar : IsBar B),
B nil.Definitionishprop_hpropdecidablebarinduction `{Funext} (A : Type)
: IsHProp (HPropDecidableBarInduction A)
:= _.
A: Type pDBI: HPropDecidableBarInduction A
DecidableBarInduction A
A: Type pDBI: HPropDecidableBarInduction A
DecidableBarInduction A
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P
P nil
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P
Tr (-1) (P nil)
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P
IsInductive (funx : list A => Tr (-1) (P x))
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P
IsBar (funx : list A => Tr (-1) (P x))
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P
IsInductive (funx : list A => Tr (-1) (P x))
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P l: list A q: foralla : A, Tr (-1) (P (l ++ [a]))
Tr (-1) (P l)
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P l: list A q: foralla : A, Tr (-1) (P (l ++ [a]))
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P
IsBar (funx : list A => Tr (-1) (P x))
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P s: nat -> A
{n : nat & Tr (-1) (P (list_restrict s n))}
A: Type pDBI: HPropDecidableBarInduction A P: list A -> Type dP: foralll : list A, Decidable (P l) iP: IsInductive P bP: IsBar P s: nat -> A
Tr (-1) (P (list_restrict s (bP s).1))
exact (tr (bP s).2).Defined.(** ** Relations between the three forms of bar induction *)(** Full bar induction clearly implies the other two. We now show that monotone bar induction implies decidable bar induction, by passing through the two-family versions. *)
A: Type MBI: MonotoneBarInduction' A
DecidableBarInduction' A
A: Type MBI: MonotoneBarInduction' A
DecidableBarInduction' A
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C
B nil
(* The [n <= length l] part is redundant, but makes it clear that [P l] is decidable, which is used below. *)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type
B nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
B nil
(* First we show that it is enough to prove [Q nil] (two cases), and then we prove [Q nil]. *)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type b0: B nil
B nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type n: nat hn: n <= length nil hc: C (take n nil)
B nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
Q nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type n: nat hn: n <= length nil hc: C (take n nil)
B nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
Q nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
Q nil
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
IsMonotone P
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
IsInductive Q
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
IsBar P
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
IsMonotone P
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l1, l2: list A n: nat cn1: n <= length l1 cn2: C (take n l1)
P (l1 ++ l2)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l1, l2: list A n: nat cn1: n <= length l1 cn2: C (take n l1)
n <= length (l1 ++ l2)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l1, l2: list A n: nat cn1: n <= length l1 cn2: C (take n l1)
C (take n (l1 ++ l2))
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l1, l2: list A n: nat cn1: n <= length l1 cn2: C (take n l1)
n <= length (l1 ++ l2)
rewrite length_app; exact _.
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l1, l2: list A n: nat cn1: n <= length l1 cn2: C (take n l1)
C (take n (l1 ++ l2))
exact (take_app l1 l2 cn1 # cn2).
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
IsInductive Q
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a])
Q l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) dP: Decidable (P l)
Q l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) t: P l
Q l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l
Q l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l
Q l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l
B l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l
foralla : A, B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A b: B (l ++ [a])
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hn: n <= length (l ++ [a]) hc: C (take n (l ++ [a]))
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hn: n <= length (l ++ [a]) hc: C (take n (l ++ [a]))
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a])
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn2: n = length (l ++ [a])
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a])
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a])
P l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a])
n <= length l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a]) hln: n <= length l
P l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a])
n <= length l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length [a] + length l
n <= length l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n.+1 <= (length l).+1
n <= length l
exact (leq_pred' hn1).
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a]) hln: n <= length l
P l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a]) hln: n <= length l
n <= length l
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a]) hln: n <= length l
C (take n l)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a]) hln: n <= length l
n <= length l
exact hln.
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn1: n < length (l ++ [a]) hln: n <= length l
C (take n l)
exact ((take_app l [a] hln)^ # hc).
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn2: n = length (l ++ [a])
B (l ++ [a])
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type l: list A hl: foralla : A, Q (l ++ [a]) f: ~ P l a: A n: nat hc: C (take n (l ++ [a])) hn2: n = length (l ++ [a])
length (l ++ [a]) <= n
bydestruct hn2^.
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type
IsBar P
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A
{n : nat & P (list_restrict s n)}
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
{n : nat & P (list_restrict s n)}
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
(n <= length (list_restrict s n)) *
C (take n (list_restrict s n))
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
n <= length (list_restrict s n)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
C (take n (list_restrict s n))
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
n <= length (list_restrict s n)
byrewrite length_list_restrict.
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
C (take n (list_restrict s n))
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
C (list_restrict s n)
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
length (list_restrict s n) <= n
A: Type MBI: MonotoneBarInduction' A B, C: list A -> Type sub: foralll : list A, C l -> B l dC: foralll : list A, Decidable (C l) indB: IsInductive B barC: IsBar C P:= funl : list A =>
{n : nat & (n <= length l) * C (take n l)}: list A -> Type Q:= funl : list A => B l + P l: list A -> Type s: nat -> A n:= (barC s).1: nat
length (list_restrict s n) <= n
byrewrite length_list_restrict.Defined.Definitiondecidable_bar_induction_monotone_bar_induction (A : Type)
(MBI : MonotoneBarInduction A)
: DecidableBarInduction A
:= funBdecindbar =>
(decidablebarinduction'_monotone_bar_induction' A
(monotonebarinduction'_monotonebarinduction A MBI))
B B (fun_ => idmap) dec ind bar.(** ** Examples of types that satisfy forms of bar induction *)(** The empty type and all contractible types satisfy full bar induction. *)
BarInduction Empty
BarInduction Empty
B: list Empty -> Type iB: IsInductive B
B nil
B: list Empty -> Type iB: IsInductive B
foralla : Empty, B (nil ++ [a])
intro a; contradiction a.Defined.
A: Type Contr0: Contr A
BarInduction A
A: Type Contr0: Contr A
BarInduction A
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B bB: IsBar B
B nil
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B bB: IsBar B c:= fun_ : nat => center A: nat -> A
B nil
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A hn: B (list_restrict c 0)
B nil
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A n: nat hn: B (list_restrict c n.+1) IHn: B (list_restrict c n) -> B nil
B nil
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A n: nat hn: B (list_restrict c n.+1) IHn: B (list_restrict c n) -> B nil
B nil
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A n: nat hn: B (list_restrict c n.+1) IHn: B (list_restrict c n) -> B nil
foralla : A, B (list_restrict c n ++ [a])
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A n: nat hn: B (list_restrict c n.+1) IHn: B (list_restrict c n) -> B nil x: A
B (list_restrict c n ++ [x])
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A n: nat hn: B (list_restrict c n.+1) IHn: B (list_restrict c n) -> B nil x: A
list_restrict c n.+1 = list_restrict c n ++ [x]
A: Type Contr0: Contr A B: list A -> Type iB: IsInductive B c:= fun_ : nat => center A: nat -> A n: nat hn: B (list_restrict c n.+1) IHn: B (list_restrict c n) -> B nil x: A
list_restrict c n.+1 = list_restrict c n ++ [center A]
napply list_restrict_succ.Defined.(** If a type satisfies decidable bar induction assuming that it is pointed, then it satisfies decidable bar induction. *)
A: Type p: A -> DecidableBarInduction A
DecidableBarInduction A
A: Type p: A -> DecidableBarInduction A
DecidableBarInduction A
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B
B nil
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B b: B nil
B nil
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil
B nil
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil
B nil
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil
foralla : A, B (nil ++ [a])
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A
B [a]
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type
B [a]
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type
IsInductive B'
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type
IsBar B'
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type
IsInductive B'
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type l: list A
(foralla0 : A, B (a :: l ++ [a0])) -> B (a :: l)
exact (iB (a :: l)).
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type
IsBar B'
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A
{n : nat & B (a :: list_restrict s n)}
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m)
{n : nat & B (a :: list_restrict s n)}
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A r: B (list_restrict (seq_cons a s) 0)
{n : nat & B (a :: list_restrict s n)}
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
{n : nat & B (a :: list_restrict s n)}
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A r: B (list_restrict (seq_cons a s) 0)
{n : nat & B (a :: list_restrict s n)}
contradiction (n r).
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
{n : nat & B (a :: list_restrict s n)}
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
B (a :: list_restrict s m)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
list_restrict (seq_cons a s) m.+1 =
a :: list_restrict s m
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
length (list_restrict (seq_cons a s) m.+1) =
length (a :: list_restrict s m)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
forall (n0 : nat)
(H : n0 < length (list_restrict (seq_cons a s) m.+1)),
nth' (list_restrict (seq_cons a s) m.+1) n0 H =
nth' (a :: list_restrict s m) n0
(transport (lt n0) ?p H)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1)
forall (n : nat)
(H : n < length (list_restrict (seq_cons a s) m.+1)),
nth' (list_restrict (seq_cons a s) m.+1) n H =
nth' (a :: list_restrict s m) n
(transport (lt n)
(internal_paths_rew_r
(funn0 : nat =>
length
(list_map
(funpat : {i : nat & i < m.+1} =>
seq_cons a s pat.1)
(reverse_acc [(m; leq_refl m.+1)]
(list_map
(functor_sigma idmap
(fun (k : nat) (H0 : k < m) =>
leq_succ_r H0))
(nat_rec
(funn1 : nat =>
list {k : nat & k < n1}) nil
(fun (n1 : nat)
(IHn : list
{k : nat & k < n1})
=>
(n1; leq_refl n1.+1)
:: list_map
(functor_sigma idmap
(...)) IHn) m)))) =
n0.+1)
(internal_paths_rew_r
(funn0 : nat => n0 = m.+1) 1
(length_list_restrict (seq_cons a s) m.+1))
(length_list_restrict s m)
:
length (list_restrict (seq_cons a s) m.+1) =
length (a :: list_restrict s m)) H)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) hk: 0 < length (list_restrict (seq_cons a s) m.+1)
nth' (list_restrict (seq_cons a s) m.+1) 0 hk =
nth' (a :: list_restrict s m) 0
(transport (lt 0)
(internal_paths_rew_r
(funn : nat =>
length
(list_map
(funpat : {i : nat & i < m.+1} =>
seq_cons a s pat.1)
(reverse_acc [(m; leq_refl m.+1)]
(list_map
(functor_sigma idmap
(fun (k : nat) (H : k < m) =>
leq_succ_r H))
(nat_rec
(funn0 : nat =>
list {k : nat & k < n0}) nil
(fun (n0 : nat)
(IHn : list
{k : nat & k < n0})
=>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap
(fun ... ... =>
leq_succ_r H)) IHn) m)))) =
n.+1)
(internal_paths_rew_r
(funn : nat => n = m.+1) 1
(length_list_restrict (seq_cons a s) m.+1))
(length_list_restrict s m)) hk)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < length (list_restrict (seq_cons a s) m.+1)
nth' (list_restrict (seq_cons a s) m.+1) k.+1 hk =
nth' (a :: list_restrict s m) k.+1
(transport (lt k.+1)
(internal_paths_rew_r
(funn : nat =>
length
(list_map
(funpat : {i : nat & i < m.+1} =>
seq_cons a s pat.1)
(reverse_acc [(m; leq_refl m.+1)]
(list_map
(functor_sigma idmap
(fun (k : nat) (H : k < m) =>
leq_succ_r H))
(nat_rec
(funn0 : nat =>
list {k : nat & k < n0}) nil
(fun (n0 : nat)
(IHn : list
{k : nat & k < n0})
=>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap
(fun ... ... =>
leq_succ_r H)) IHn) m)))) =
n.+1)
(internal_paths_rew_r
(funn : nat => n = m.+1) 1
(length_list_restrict (seq_cons a s) m.+1))
(length_list_restrict s m)) hk)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < length (list_restrict (seq_cons a s) m.+1)
nth' (list_restrict (seq_cons a s) m.+1) k.+1 hk =
nth' (a :: list_restrict s m) k.+1
(transport (lt k.+1)
(internal_paths_rew_r
(funn : nat =>
length
(list_map
(funpat : {i : nat & i < m.+1} =>
seq_cons a s pat.1)
(reverse_acc [(m; leq_refl m.+1)]
(list_map
(functor_sigma idmap
(fun (k : nat) (H : k < m) =>
leq_succ_r H))
(nat_rec
(funn0 : nat =>
list {k : nat & k < n0}) nil
(fun (n0 : nat)
(IHn : list
{k : nat & k < n0})
=>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap
(fun ... ... =>
leq_succ_r H)) IHn) m)))) =
n.+1)
(internal_paths_rew_r
(funn : nat => n = m.+1) 1
(length_list_restrict (seq_cons a s) m.+1))
(length_list_restrict s m)) hk)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < length (list_restrict (seq_cons a s) m.+1)
k < length (list_restrict s m)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < length (list_restrict (seq_cons a s) m.+1) hk': k < length (list_restrict s m)
nth' (list_restrict (seq_cons a s) m.+1) k.+1 hk =
nth' (a :: list_restrict s m) k.+1
(transport (lt k.+1)
(internal_paths_rew_r
(funn : nat =>
length
(list_map
(funpat : {i : nat & i < m.+1} =>
seq_cons a s pat.1)
(reverse_acc [(m; leq_refl m.+1)]
(list_map
(functor_sigma idmap
(fun (k : nat) (H : k < m) =>
leq_succ_r H))
(nat_rec
(funn0 : nat =>
list {k : nat & k < n0}) nil
(fun (n0 : nat)
(IHn : list
{k : nat & k < n0})
=>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap
(fun ... ... =>
leq_succ_r H)) IHn) m)))) =
n.+1)
(internal_paths_rew_r
(funn : nat => n = m.+1) 1
(length_list_restrict (seq_cons a s) m.+1))
(length_list_restrict s m)) hk)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < length (list_restrict (seq_cons a s) m.+1)
k < length (list_restrict s m)
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < m.+1
k < m
exact _.
A: Type p: A -> DecidableBarInduction A B: list A -> Type dB: foralll : list A, Decidable (B l) iB: IsInductive B bB: IsBar B n: ~ B nil a: A B':= funl : list A => B (a :: l): list A -> Type s: nat -> A m: nat r: B (list_restrict (seq_cons a s) m.+1) k: nat hk: k.+1 < length (list_restrict (seq_cons a s) m.+1) hk': k < length (list_restrict s m)
nth' (list_restrict (seq_cons a s) m.+1) k.+1 hk =
nth' (a :: list_restrict s m) k.+1
(transport (lt k.+1)
(internal_paths_rew_r
(funn : nat =>
length
(list_map
(funpat : {i : nat & i < m.+1} =>
seq_cons a s pat.1)
(reverse_acc [(m; leq_refl m.+1)]
(list_map
(functor_sigma idmap
(fun (k : nat) (H : k < m) =>
leq_succ_r H))
(nat_rec
(funn0 : nat =>
list {k : nat & k < n0}) nil
(fun (n0 : nat)
(IHn : list
{k : nat & k < n0})
=>
(n0; leq_refl n0.+1)
:: list_map
(functor_sigma idmap
(fun ... ... =>
leq_succ_r H)) IHn) m)))) =
n.+1)
(internal_paths_rew_r
(funn : nat => n = m.+1) 1
(length_list_restrict (seq_cons a s) m.+1))
(length_list_restrict s m)) hk)
byrewrite (nth'_cons _ _ _ hk'), !nth'_list_restrict.Defined.(** The same is true for monotone bar induction. *)
A: Type p: A -> MonotoneBarInduction A
MonotoneBarInduction A
A: Type p: A -> MonotoneBarInduction A
MonotoneBarInduction A
A: Type p: A -> MonotoneBarInduction A B: list A -> Type mB: IsMonotone B iB: IsInductive B bB: IsBar B
B nil
A: Type p: A -> MonotoneBarInduction A B: list A -> Type mB: IsMonotone B iB: IsInductive B bB: IsBar B
foralla : A, B (nil ++ [a])
A: Type p: A -> MonotoneBarInduction A B: list A -> Type mB: IsMonotone B iB: IsInductive B bB: IsBar B a: A
B [a]
byapply (mB nil), (p a).Defined.(** Combining [monotonebarinduction_pointed_monotonebarinduction] and [barinduction_contr], we prove that any proposition satisfies monotone bar induction. *)
A: Type IsHProp0: IsHProp A
MonotoneBarInduction A
A: Type IsHProp0: IsHProp A
MonotoneBarInduction A
A: Type IsHProp0: IsHProp A
A -> MonotoneBarInduction A
A: Type IsHProp0: IsHProp A a: A
MonotoneBarInduction A
A: Type IsHProp0: IsHProp A a: A BI: BarInduction A
MonotoneBarInduction A
A: Type IsHProp0: IsHProp A a: A
BarInduction A
A: Type IsHProp0: IsHProp A a: A
BarInduction A
apply barinduction_contr, (contr_inhabited_hprop A a).Defined.(** Note that [monotone_bar_induction_pointed_monotone_bar_induction] does not have an analogue for full bar induction. We prove below that every type satisfying full bar induction is Sigma-compact and therefore decidable. Then, as in [monotone_bar_induction_hprop], we would be able to prove that any proposition satisfies bar induction and therefore that every proposition is decidable. *)(** ** Implications of bar induction *)(** Full bar induction for a type [A] implies that it is Sigma-compact, in the sense that any decidable family over [A] has a decidable Sigma-type. To prove this, we begin by defining a type family [P] on [list A] so that [P nil] is our goal. *)DefinitionBI_sig_family {A : Type} (P : A -> Type) (l : list A) : Type
:= match l with
| nil => Decidable {a : A & P a}
| a :: l' => ~(P a)
end.
A: Type P: A -> Type dec: foralln : A, Decidable (P n)
IsBar (BI_sig_family P)
A: Type P: A -> Type dec: foralln : A, Decidable (P n)
IsBar (BI_sig_family P)
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A
{n : nat & BI_sig_family P (list_restrict s n)}
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p: P (s 0)
{n : nat & BI_sig_family P (list_restrict s n)}
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p': ~ P (s 0)
{n : nat & BI_sig_family P (list_restrict s n)}
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p: P (s 0)
{n : nat & BI_sig_family P (list_restrict s n)}
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p: P (s 0)
BI_sig_family P (list_restrict s 0)
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p: P (s 0)
Decidable {a : A & P a}
exact (inl (s 0; p)).
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p': ~ P (s 0)
{n : nat & BI_sig_family P (list_restrict s n)}
A: Type P: A -> Type dec: foralln : A, Decidable (P n) s: nat -> A p': ~ P (s 0)
BI_sig_family P (list_restrict s 1)
exact p'.Defined.
A: Type P: A -> Type
IsInductive (BI_sig_family P)
A: Type P: A -> Type
IsInductive (BI_sig_family P)
A: Type P: A -> Type h: foralla : A, BI_sig_family P (nil ++ [a])
BI_sig_family P nil
A: Type P: A -> Type a: A l: list A h: foralla0 : A, BI_sig_family P ((a :: l) ++ [a0])
BI_sig_family P (a :: l)
A: Type P: A -> Type h: foralla : A, BI_sig_family P (nil ++ [a])
BI_sig_family P nil
A: Type P: A -> Type h: foralla : A, BI_sig_family P (nil ++ [a])
~ {a : A & P a}
exact (funpa => h pa.1 pa.2).
A: Type P: A -> Type a: A l: list A h: foralla0 : A, BI_sig_family P ((a :: l) ++ [a0])
BI_sig_family P (a :: l)
exact (h a).Defined.Definitionissigcompact_barinduction {A : Type} (BI : BarInduction A)
(P : A -> Type) (dec : foralln : A, Decidable (P n))
: Decidable {a : A & P a}
:= BI (BI_sig_family P)
(isinductive_BI_sig_family P) (is_bar_BI_sig_family dec).(** Full bar induction for [nat] implies the limited principle of omniscience, i.e., for every sequence of natural numbers we can decide whether every term is zero or there exists a non-zero term. *)
BI: BarInduction nat s: nat -> nat
(foralln : nat, s n = 0) + {n : nat & s n <> 0}
BI: BarInduction nat s: nat -> nat
(foralln : nat, s n = 0) + {n : nat & s n <> 0}
BI: BarInduction nat s: nat -> nat l: {a : nat & s a <> 0}
(foralln : nat, s n = 0) + {n : nat & s n <> 0}
BI: BarInduction nat s: nat -> nat r: ~ {a : nat & s a <> 0}
(foralln : nat, s n = 0) + {n : nat & s n <> 0}
BI: BarInduction nat s: nat -> nat l: {a : nat & s a <> 0}
(foralln : nat, s n = 0) + {n : nat & s n <> 0}
right; exact l.
BI: BarInduction nat s: nat -> nat r: ~ {a : nat & s a <> 0}
(foralln : nat, s n = 0) + {n : nat & s n <> 0}
left; exact (funn => stable (funz : s n <> 0 => r (n; z))).Defined.