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.
(** * Theorems about the booleans *)
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Require Import Types.Equiv.LocalOpen Scope path_scope.(* Coq calls it "bool", we call it "Bool" *)Local Unset Elimination Schemes.InductiveBool : Type0 :=
| true : Bool
| false : Bool.SchemeBool_ind := Induction for Bool SortType.SchemeBool_rec := Minimality for Bool SortType.(* For compatibility with Coq's [induction] *)DefinitionBool_rect := Bool_ind.Add Printing If Bool.Declare Scope bool_scope.Delimit Scope bool_scope with Bool.Bind Scope bool_scope with Bool.Definitionandb (b1b2 : Bool) : Bool := if b1 then b2 else false.Definitionorb (b1b2 : Bool) : Bool := if b1 then true else b2.Definitionnegb (b : Bool) := if b then false else true.Definitionimplb (b1b2 : Bool) : Bool := if b1 then b2 else true.Infix"||" := orb : bool_scope.Infix"&&" := andb : bool_scope.Infix"->" := implb : bool_scope.Definitionimplb_true {b} : implb b true = true
:= if b as b return implb b true = true then idpath else idpath.
a, b: Bool
(a -> b)%Bool = true <-> (a = true -> b = true)
a, b: Bool
(a -> b)%Bool = true <-> (a = true -> b = true)
destruct a; simpl; split; trivial using idpath with nocore;
destruct b; simpl; auto using idpath with nocore.Defined.Instancetrunc_ifnAB `{IsTrunc n A, IsTrunc n B} (b : Bool)
: IsTrunc n (if b then A else B) | 100
:= if b as b return (IsTrunc n (if b then A else B)) then _ else _.(** ** Decidability *)SectionBoolDecidable.Definitionfalse_ne_true : ~ (false = true)
:= funH => match H in (_ = y) return (if y returnSetthen Empty else Bool) with
| 1%path => true
end.Definitiontrue_ne_false : ~ (true = false)
:= funH => false_ne_true (symmetry _ _ H).#[export] Instancedecidable_paths_bool : DecidablePaths Bool
:= funxy => match x as x, y as y return ((x = y) + ~(x = y)) with
| true, true => inl idpath
| false, false => inl idpath
| true, false => inr true_ne_false
| false, true => inr false_ne_true
end.Definitionhset_bool : IsHSet Bool := _.EndBoolDecidable.(** In particular, [negb] has no fixed points *)Definitionnot_fixed_negb (b : Bool) : negb b <> b
:= match b return negb b <> b with
| true => false_ne_true
| false => true_ne_false
end.(** And conversely, if two elements of [Bool] are unequal, they must be related by [negb]. *)
b1, b2: Bool
b1 <> b2 -> b1 = negb b2
b1, b2: Bool
b1 <> b2 -> b1 = negb b2
true <> true -> true = negb true
true <> false -> true = negb false
false <> true -> false = negb true
false <> false -> false = negb false
true <> true -> true = negb true
intros oops; case (oops idpath).
true <> false -> true = negb false
reflexivity.
false <> true -> false = negb true
reflexivity.
false <> false -> false = negb false
intros oops; case (oops idpath).Defined.(** This version of [negb_ne] is more convenient to [destruct] against. *)
b1, b2: Bool
b1 <> b2 -> negb b1 = b2
b1, b2: Bool
b1 <> b2 -> negb b1 = b2
b1, b2: Bool oops: b1 <> b2
negb b1 = b2
b1, b2: Bool oops: b1 <> b2
b2 = negb b1
b1, b2: Bool oops: b1 <> b2
b2 <> b1
exact (symmetric_neq oops).Defined.(** ** Products as [forall] over [Bool] *)SectionBoolForall.VariableP : Bool -> Type.Letf (s : forallb, P b) := (s false, s true).Letg (u : P false * P true) (b : Bool) : P b :=
match b with
| false => fst u
| true => snd u
end.
P: Bool -> Type f:= funs : forallb : Bool, P b => (s false, s true): (forallb : Bool, P b) -> P false * P true g:= fun (u : P false * P true) (b : Bool) =>
if b as b0 return (P b0) then snd u else fst u: P false * P true -> forallb : Bool, P b H: Funext
(forallb : Bool, P b) <~> P false * P true
P: Bool -> Type f:= funs : forallb : Bool, P b => (s false, s true): (forallb : Bool, P b) -> P false * P true g:= fun (u : P false * P true) (b : Bool) =>
if b as b0 return (P b0) then snd u else fst u: P false * P true -> forallb : Bool, P b H: Funext
(forallb : Bool, P b) <~> P false * P true
apply (equiv_adjointify f g);
repeat (reflexivity
|| intros []
|| intro
|| apply path_forall).Defined.EndBoolForall.Definitionequiv_bool_rec_uncurried `{Funext} (P : Type) : P * P <~> (Bool -> P)
:= (equiv_bool_forall_prod (fun_ => P))^-1%equiv.(** ** The type [Bool <~> Bool] is equivalent to [Bool]. *)(** The non-identity equivalence is negation (the flip). *)
IsEquiv negb
IsEquiv negb
forallx : Bool,
(if negb x as b return (negb (negb b) = b)
then1else1) =
ap negb
(if x as b return (negb (negb b) = b) then1else1)
intros []; simpl; exact idpath.Defined.Definitionequiv_negb : Bool <~> Bool
:= Build_Equiv Bool Bool negb _.(** Any equivalence [Bool <~> Bool] sends [true] and [false] to different things. *)
f: Bool -> Bool H: IsEquiv f
f false = negb (f true)
f: Bool -> Bool H: IsEquiv f
f false = negb (f true)
f: Bool -> Bool H: IsEquiv f X: (f^-1 o f) true = idmap true
f false = negb (f true)
f: Bool -> Bool H: IsEquiv f X: (f^-1 o f) true = idmap true X0: (f^-1 o f) false = idmap false
etransitivity; try (eassumption || (symmetry; eassumption)).Defined.SectionEquivBoolEquiv.(** We will identify the constant equivalence with [true] and the flip equivalence with [false], and do this by evaluating the equivalence function on [true]. *)Letf : (Bool <~> Bool) -> Bool := fune => e true.Letg : Bool -> (Bool <~> Bool) := funb => if b
then (equiv_idmap Bool)
else equiv_negb.