<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://www.glc.us.es/~jalonso/DAOconCoq/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jalonso</id>
	<title>DAO con Coq - Contribuciones del usuario [es]</title>
	<link rel="self" type="application/atom+xml" href="https://www.glc.us.es/~jalonso/DAOconCoq/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jalonso"/>
	<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php/Especial:Contribuciones/Jalonso"/>
	<updated>2026-09-20T05:18:47Z</updated>
	<subtitle>Contribuciones del usuario</subtitle>
	<generator>MediaWiki 1.31.14</generator>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T6_Logica.v&amp;diff=76</id>
		<title>Archivo:T6 Logica.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T6_Logica.v&amp;diff=76"/>
		<updated>2018-08-20T11:00:14Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=75</id>
		<title>Tema 5: Tácticas básicas de Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=75"/>
		<updated>2018-08-20T10:59:35Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se amplían las tácticas básicas estudiadas en los temas anteriores. Al final de la teoría se incluye un resumen de todas las tácticas usadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T5_Tacticas.v|T5_Tacticas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T5: Tácticas básicas de Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T4_PolimorfismoyOS.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   5. Control de la hipótesis de inducción  &lt;br /&gt;
   6. Expansión de definiciones &lt;br /&gt;
   7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   8. Ejercicios &lt;br /&gt;
   9. Resumen de tácticas básicas &lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== La táctica &amp;#039;apply&amp;#039; == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que &lt;br /&gt;
          n = m  -&amp;gt;&lt;br /&gt;
          [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
          [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración sin apply *)&lt;br /&gt;
Theorem artificial_1a : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  rewrite H2.           (* [n; p] = [n; p] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* Demostración con apply *)&lt;br /&gt;
Theorem artificial_1b : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que &lt;br /&gt;
      n = m  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
      [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2 : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : forall q r : nat, q = r -&amp;gt; [q; o] = [r; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  apply H2.             (* n = m *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039; en hipótesis condicionales y&lt;br /&gt;
   razonamiento hacia atrás&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Demostrar que &lt;br /&gt;
      (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
      [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2a : forall (n m : nat),&lt;br /&gt;
    (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H1 H2. (* n, m : nat&lt;br /&gt;
                       H1 : (n, n) = (m, m)&lt;br /&gt;
                       H2 : forall q r : nat, (q, q) = (r, r) -&amp;gt; [q] = [r]&lt;br /&gt;
                       ============================&lt;br /&gt;
                       [n] = [m] *)&lt;br /&gt;
  apply H2.         (* (n, n) = (m, m) *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar, sin usar simpl, que&lt;br /&gt;
      (forall n, evenb n = true -&amp;gt; oddb (S n) = true) -&amp;gt;&lt;br /&gt;
      evenb 3 = true -&amp;gt;&lt;br /&gt;
      oddb 4 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial_ex :&lt;br /&gt;
  (forall n, esPar n = true -&amp;gt; esImpar (S n) = true) -&amp;gt;&lt;br /&gt;
  esPar 3 = true -&amp;gt;&lt;br /&gt;
  esImpar 4 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 H2. (* H1 : forall n : nat, esPar n = true -&amp;gt; esImpar (S n) = true&lt;br /&gt;
                   H2 : esPar 3 = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   esImpar 4 = true *)&lt;br /&gt;
  apply H1.     (* esPar 3 = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Demostrar que &lt;br /&gt;
      true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
      iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3a: forall (n : nat),&lt;br /&gt;
    true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
    iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H. (* n : nat&lt;br /&gt;
                 H : true = iguales_nat n 5&lt;br /&gt;
                 ============================&lt;br /&gt;
                 iguales_nat (S (S n)) 7 = true *)&lt;br /&gt;
  symmetry.   (* true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  simpl.      (* true = iguales_nat n 5 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Necesidad de usar symmetry antes de apply.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar&lt;br /&gt;
      forall (xs ys : list nat), &lt;br /&gt;
       xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa2: forall (xs ys : list nat),&lt;br /&gt;
    xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.           (* xs, ys : list nat&lt;br /&gt;
                               H : xs = inversa ys&lt;br /&gt;
                               ============================&lt;br /&gt;
                               ys = inversa xs *)&lt;br /&gt;
  rewrite H.                (* ys = inversa (inversa ys) *)&lt;br /&gt;
  symmetry.                 (* inversa (inversa ys) = ys *)&lt;br /&gt;
  apply inversa_involutiva. &lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== La táctica &amp;#039;apply ... with ...&amp;#039; == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall (a b c d e f : nat),&lt;br /&gt;
       [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
       [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
       [a;b] = [e;f].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejemplo_con_transitiva: forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2. (* a, b, c, d, e, f : nat&lt;br /&gt;
                               H1 : [a; b] = [c; d]&lt;br /&gt;
                               H2 : [c; d] = [e; f]&lt;br /&gt;
                               ============================&lt;br /&gt;
                               [a; b] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H1.             (* [c; d] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H2.             (* [e; f] = [e; f] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem igualdad_transitiva: forall (X:Type) (n m o : X),&lt;br /&gt;
    n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X n m o H1 H2. (* X : Type&lt;br /&gt;
                           n, m, o : X&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : m = o&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.         (* m = o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.         (* o = o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El ejercicio 2.2 es una generalización del 2.1, sus&lt;br /&gt;
   demostraciones son isomorfas y se puede usar el 2.2 en la&lt;br /&gt;
   demostración del 2.1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.                  (* a, b, c, d, e, f : nat&lt;br /&gt;
                                                H1 : [a; b] = [c; d]&lt;br /&gt;
                                                H2 : [c; d] = [e; f]&lt;br /&gt;
                                                ============================&lt;br /&gt;
                                                [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with (m:=[c;d]).&lt;br /&gt;
  -                                          (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                          (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039;&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.             (* a, b, c, d, e, f : nat&lt;br /&gt;
                                           H1 : [a; b] = [c; d]&lt;br /&gt;
                                           H2 : [c; d] = [e; f]&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with [c;d].&lt;br /&gt;
  -                                     (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                     (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply ... whith ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1. Demostrar que&lt;br /&gt;
      forall (n m o p : nat),&lt;br /&gt;
        m = (menosDos o) -&amp;gt;&lt;br /&gt;
        (n + p) = m -&amp;gt;&lt;br /&gt;
        (n + p) = (menosDos o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_igualdad_transitiva: forall (n m o p : nat),&lt;br /&gt;
    m = (menosDos o) -&amp;gt;&lt;br /&gt;
    (n + p) = m -&amp;gt;&lt;br /&gt;
    (n + p) = (menosDos o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2.             (* n, m, o, p : nat&lt;br /&gt;
                                       H1 : m = menosDos o&lt;br /&gt;
                                       H2 : n + p = m&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n + p = menosDos o *)&lt;br /&gt;
  apply igualdad_transitiva with m. &lt;br /&gt;
  -                                 (* n + p = m *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
  -                                 (* m = menosDos o *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== La táctica &amp;#039;inversion&amp;#039; == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       S n = S m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inyectiva: forall (n m : nat),&lt;br /&gt;
  S n = S m -&amp;gt;&lt;br /&gt;
  n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (n m o : nat),&lt;br /&gt;
       [n; m] = [o; o] -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej1: forall (n m o : nat),&lt;br /&gt;
    [n; m] = [o; o] -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H. (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [n] = [m] *)&lt;br /&gt;
  inversion H.    (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     H1 : n = o&lt;br /&gt;
                     H2 : m = o&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [o] = [o] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       [n] = [m] -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej2: forall (n m : nat),&lt;br /&gt;
    [n] = [m] -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.         (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = m *)&lt;br /&gt;
  inversion H as [Hnm]. (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           Hnm : n = m&lt;br /&gt;
                           ============================&lt;br /&gt;
                           m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Nombramiento de las hipótesis generadas por inversión.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
        x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej3 : forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
  x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
  y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
  x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H1 H2. (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x = y *)&lt;br /&gt;
  inversion H1.               (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = y *)&lt;br /&gt;
  inversion H2.               (* xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 H4 : y = x&lt;br /&gt;
                                 H5 : xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = x *)&lt;br /&gt;
  symmetry.                   (* x = z *)&lt;br /&gt;
  apply H0.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.4. Demostrar que&lt;br /&gt;
      forall n:nat,&lt;br /&gt;
       iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_0_n: forall n:nat,&lt;br /&gt;
    iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 n = true -&amp;gt; n = 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
    intros H.           (* H : iguales_nat 0 0 = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 (S n&amp;#039;) = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    intros H.           (* n&amp;#039; : nat&lt;br /&gt;
                           H : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           S n&amp;#039; = 0 *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.5. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       S n = O -&amp;gt; 2 + 2 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej4: forall (n : nat),&lt;br /&gt;
    S n = O -&amp;gt;&lt;br /&gt;
    2 + 2 = 5.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.  (* n : nat&lt;br /&gt;
                  H : S n = 0&lt;br /&gt;
                  ============================&lt;br /&gt;
                  2 + 2 = 5 *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.6. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       false = true -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej5: forall (n m : nat),&lt;br /&gt;
    false = true -&amp;gt; [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : false = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   [n] = [m] *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
        y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        x = z.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej6 :&lt;br /&gt;
  forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
    x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
    y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
    x = z.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H. (* X : Type&lt;br /&gt;
                             x, y, z : X&lt;br /&gt;
                             xs, ys : list X&lt;br /&gt;
                             H : x :: y :: xs = [ ]&lt;br /&gt;
                             ============================&lt;br /&gt;
                             y :: xs = z :: ys -&amp;gt; x = z *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.  &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.7. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
       x = y -&amp;gt; f x = f y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem funcional: forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
    x = y -&amp;gt; f x = f y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f x y H. (* A : Type&lt;br /&gt;
                         B : Type&lt;br /&gt;
                         f : A -&amp;gt; B&lt;br /&gt;
                         x, y : A&lt;br /&gt;
                         H : x = y&lt;br /&gt;
                         ============================&lt;br /&gt;
                         f x = f y *)&lt;br /&gt;
  rewrite H.          (* f y = f y *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Uso de tácticas sobre las hipótesis == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n m : nat) (b : bool),&lt;br /&gt;
       iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
       iguales_nat n m = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inj: forall (n m : nat) (b : bool),&lt;br /&gt;
    iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
    iguales_nat n m = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m b H. (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat (S n) (S m) = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  simpl in H.     (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat n m = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de táctica &amp;#039;simpl in ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
       true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
       true = iguales_nat (S (S n)) 7.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3&amp;#039;: forall (n : nat),&lt;br /&gt;
  (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
  true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
  true = iguales_nat (S (S n)) 7.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H1 H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat n 5&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat n 5 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H1 in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat (S (S n)) 7&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de las tácticas &amp;#039;apply H1 in H2&amp;#039; y &amp;#039;symemetry in H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n + n = m + m -&amp;gt;&lt;br /&gt;
        n = m.&lt;br /&gt;
&lt;br /&gt;
   Nota: Usar suma_s_Sm.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_n_inyectiva:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    n + n = m + m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, n + n = m + m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI]. &lt;br /&gt;
  -                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, 0 + 0 = m + m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H1.                 (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* H1 : 0 + 0 = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = S m *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, S n&amp;#039; + S n&amp;#039; = m + m &lt;br /&gt;
                                                    -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H2.                 (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H2.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H2.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : n&amp;#039; + S n&amp;#039; = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (n&amp;#039; + n&amp;#039;) = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H0.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : m + S m = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H0.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : m + m = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      apply HI in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- H1.             (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Control de la hipótesis de inducción == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª intento *)&lt;br /&gt;
Theorem doble_inyectiva_FAILED : forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.             (* n, m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros H.             (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble (S n&amp;#039;) = doble m -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros H.             (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva: forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H.           (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble (S n&amp;#039;) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, S (S (doble n&amp;#039;)) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H.           (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.           (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.        (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la estrategia de generalización.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_true : forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat 0 m = true &lt;br /&gt;
                                              -&amp;gt; 0 = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 (S m&amp;#039;) = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat (S n&amp;#039;) m = true&lt;br /&gt;
                                                   -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) 0 = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                        -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) (S m&amp;#039;) = true &lt;br /&gt;
                                   -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* iguales_nat n&amp;#039; m&amp;#039; = true -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : iguales_nat n&amp;#039; m&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply HIn&amp;#039; in H.          (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      rewrite H.                (* S m&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
    &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2a: forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI].&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                      (* doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros H.                   (* n : nat&lt;br /&gt;
                                   H : doble n = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                           (* H : doble 0 = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.               (* n&amp;#039; : nat&lt;br /&gt;
                                   H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble (S m&amp;#039;) -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
&lt;br /&gt;
    intros H.                   (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.               (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble (S n&amp;#039;) = doble m&amp;#039; -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.          (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2 : forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.               (* n, m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  generalize dependent n.   (* m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI]. &lt;br /&gt;
  -                         (*  &lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                  (* forall n : nat, doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros n H.             (* n : nat&lt;br /&gt;
                               H : doble n = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                       (* H : doble 0 = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                       (* n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.           (* n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                         (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble (S m&amp;#039;) &lt;br /&gt;
                                               -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
    intros n H.             (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n : nat&lt;br /&gt;
                               H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.      (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.             (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.          (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;generalize dependent n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Demostrar que&lt;br /&gt;
      forall x y : id,&lt;br /&gt;
       iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_true: forall x y : id,&lt;br /&gt;
  iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [m] [n].           (* m, n : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id (Id m) (Id n) = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  simpl.                    (* iguales_nat m n = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  intros H.                 (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
  assert (H&amp;#039; : m = n).&lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               m = n *)&lt;br /&gt;
    apply iguales_nat_true. (* iguales_nat m n = true *)&lt;br /&gt;
    apply H. &lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               H&amp;#039; : m = n&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
    rewrite H&amp;#039;.             (* Id n = Id n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar, por inducción sobre l,&lt;br /&gt;
      forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
        longitud xs = n -&amp;gt;&lt;br /&gt;
        nthOpcional xs n = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nthOpcional_None: forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = n -&amp;gt;&lt;br /&gt;
    nthOpcional xs n = None.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n X xs.               (* n : nat&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  generalize dependent n.       (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud [] = n -&amp;gt; nthOpcional [] n = None *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = n -&amp;gt; &lt;br /&gt;
                                   nthOpcional (x :: xs&amp;#039;) n = None *)&lt;br /&gt;
    destruct n as [|n&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = 0 -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) (S n&amp;#039;) = None *)&lt;br /&gt;
      simpl.                    (* S (longitud xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                   nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      apply HI.                 (* longitud xs&amp;#039; = n&amp;#039; *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  H1 : longitud xs&amp;#039; = n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs&amp;#039; = longitud xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Expansión de definiciones == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.1. Definir la función&lt;br /&gt;
      cuadrado : nata -&amp;gt; nat&lt;br /&gt;
   tal que (cuadrado n) es el cuadrado de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition cuadrado (n:nat) : nat := n * n.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuadrado_mult : forall n m : nat,&lt;br /&gt;
    cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                            (* n, m : nat&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            cuadrado (n * m) = &lt;br /&gt;
                                            cuadrado n * cuadrado m *)&lt;br /&gt;
  unfold cuadrado.                       (* (n * m) * (n * m) = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  rewrite producto_asociativa.           (* ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  assert (H : (n * m) * n = (n * n) * m). &lt;br /&gt;
  -                                      (* (n * m) * n = (n * n) * m) *)&lt;br /&gt;
    rewrite producto_conmutativa.        (* n * (n * m) = (n * n) * m *)&lt;br /&gt;
    apply producto_asociativa.           &lt;br /&gt;
  -                                      (* n, m : nat&lt;br /&gt;
                                            H : (n * m) * n = (n * n) * m&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite H.                           (* ((n * n) * m) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite producto_asociativa.         (* ((n * n) * m) * m = &lt;br /&gt;
                                            ((n * n) * m) * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;unfold&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.4. Definir la función&lt;br /&gt;
      const5 : nat -&amp;gt; nat&lt;br /&gt;
   tal que (const5 x) es el número 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5 (x: nat) : nat := 5.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.5. Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact prop_const5 : forall m : nat,&lt;br /&gt;
    const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.    (* m : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  const5 m + 1 = const5 (m + 1) + 1 *)&lt;br /&gt;
  simpl.       (* 6 = 6 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Expansión automática de la definición de const5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.6. Se coonsidera la siguiente definición&lt;br /&gt;
      Definition const5b (x:nat) : nat :=&lt;br /&gt;
        match x with&lt;br /&gt;
        | O   =&amp;gt; 5&lt;br /&gt;
        | S _ =&amp;gt; 5&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5b (x:nat) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | O   =&amp;gt; 5&lt;br /&gt;
  | S _ =&amp;gt; 5&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fact prop_const5b_1: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m. (* m : nat&lt;br /&gt;
               ============================&lt;br /&gt;
               const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  simpl.    (* const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Fact prop_const5b_2: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.      (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b 0 + 1 = const5b (0 + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b (S m) + 1 = const5b (S m + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Fact prop_const5b_3: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.       (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  unfold const5b. (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     match m with&lt;br /&gt;
                     | 0 | _ =&amp;gt; 5&lt;br /&gt;
                     end + 1 = match m + 1 with&lt;br /&gt;
                               | 0 | _ =&amp;gt; 5&lt;br /&gt;
                               end + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -               (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match 0 + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match S m + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.1. Se considera la siguiente definición &lt;br /&gt;
      Definition const_false (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then false&lt;br /&gt;
        else if iguales_nat n 5 then false&lt;br /&gt;
        else                         false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       const_false n = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const_false (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then false&lt;br /&gt;
  else if iguales_nat n 5 then false&lt;br /&gt;
  else                         false.&lt;br /&gt;
&lt;br /&gt;
Theorem const_false_false : forall n : nat,&lt;br /&gt;
    const_false n = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                     (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   const_false n = false *)&lt;br /&gt;
  unfold const_false.           (* (if iguales_nat n 3 then false &lt;br /&gt;
                                   else if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) =&lt;br /&gt;
                                   false *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) = false *)&lt;br /&gt;
    destruct (iguales_nat n 5). &lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.2. Se considera la siguiente definición &lt;br /&gt;
      Definition ej (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then true&lt;br /&gt;
        else if iguales_nat n 5 then true&lt;br /&gt;
        else                     false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       ej n = true -&amp;gt; esImpar n = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ej (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then true&lt;br /&gt;
  else if iguales_nat n 5 then true&lt;br /&gt;
  else                     false.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem ej_impar_a: forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                       (* n : nat&lt;br /&gt;
                                       H : ej n = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       esImpar n = true *)&lt;br /&gt;
  unfold ej in H. (* n : nat&lt;br /&gt;
                                      H : (if iguales_nat n 3&lt;br /&gt;
                                           then true&lt;br /&gt;
                                           else if iguales_nat n 5 &lt;br /&gt;
                                                then true &lt;br /&gt;
                                                else false) &lt;br /&gt;
                                          = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                                (* n : nat&lt;br /&gt;
                                      H : true = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem ej_impar : forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                             (* n : nat&lt;br /&gt;
                                             H : ej n = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  unfold ej in H.                         (* n : nat&lt;br /&gt;
                                             H : (if iguales_nat n 3&lt;br /&gt;
                                                  then true&lt;br /&gt;
                                                  else if iguales_nat n 5 &lt;br /&gt;
                                                       then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3) eqn: H3.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    apply iguales_nat_true in H3.         (* n : nat&lt;br /&gt;
                                             H3 : n = 3&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    rewrite H3.                           (* esImpar 3 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H : (if iguales_nat n 5 &lt;br /&gt;
                                                  then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    destruct (iguales_nat n 5) eqn:H5. &lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      apply iguales_nat_true in H5.       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : n = 5&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      rewrite H5.                         (* esImpar 5 = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = false&lt;br /&gt;
                                             H : false = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct e eqn: H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.1. Demostrar que desempareja y empareja son inversas; es decir,&lt;br /&gt;
        forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
          desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
          empareja xs ys = ps.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem empareja_desempareja: forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
    desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
    empareja xs ys = ps.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y ps.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ps : list (X * Y)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ps = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = ps *)&lt;br /&gt;
  induction ps as [|(x,y) ps&amp;#039; HI].&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja [ ] = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = [ ] *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja [ ] = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          H1 : [ ] = xs&lt;br /&gt;
                                          H2 : [ ] = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja [ ] [ ] = [ ] *)&lt;br /&gt;
    simpl.                             (* [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) &lt;br /&gt;
                                               -&amp;gt; empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ((x,y)::ps&amp;#039;) = (xs,ys) &lt;br /&gt;
                                           -&amp;gt; empareja xs ys = (x,y)::ps&amp;#039; *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    destruct (desempareja ps&amp;#039;) eqn: E. (* Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs: ist X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : match desempareja ps&amp;#039; with&lt;br /&gt;
                                              | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                              end = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite E in H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja (x :: l) (y :: l0) = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl.                             (* (x, y) :: empareja l l0 = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite HI.&lt;br /&gt;
    +                                  (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (x, y) :: ps&amp;#039; = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                  (*   X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (l, l0) = (l, l0)&lt;br /&gt;
 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.2. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
        f (f (f b)) = f b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem bool_tres_veces:&lt;br /&gt;
  forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
    f (f (f b)) = f b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f b.                    (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f b)) = f b *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f true)) = f true *)&lt;br /&gt;
    destruct (f true) eqn:H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      rewrite H1.                (* f true = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      destruct (f false) eqn:H2. &lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = false *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = false *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f false)) = f false *)&lt;br /&gt;
    destruct (f false) eqn:H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      destruct (f true) eqn:H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = true *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      rewrite H3.                (* f false = false *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ejercicios == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        iguales_nat n m = iguales_nat m n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_simetrica: forall n m : nat,&lt;br /&gt;
    iguales_nat n m = iguales_nat m n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                          (* n, m : nat&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          iguales_nat n m = iguales_nat m n *)&lt;br /&gt;
  destruct (iguales_nat n m) eqn:H1.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    apply iguales_nat_true in H1.      (* n, m : nat&lt;br /&gt;
                                          H1 : n = m&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    rewrite H1.                        (* true = iguales_nat m m *)&lt;br /&gt;
    symmetry.                          (* iguales_nat m m = true *)&lt;br /&gt;
    apply iguales_nat_refl.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = iguales_nat m n *)&lt;br /&gt;
    destruct (iguales_nat m n) eqn:H2. &lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      apply iguales_nat_true in H2.    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite H2 in H1.                (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n n = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite iguales_nat_refl in H1.  (* n, m : nat&lt;br /&gt;
                                          H1 : true = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.2. Demostrar que&lt;br /&gt;
        forall n m p : nat,&lt;br /&gt;
          iguales_nat n m = true -&amp;gt;&lt;br /&gt;
          iguales_nat m p = true -&amp;gt;&lt;br /&gt;
          iguales_nat n p = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_trans: forall n m p : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt;&lt;br /&gt;
    iguales_nat m p = true -&amp;gt;&lt;br /&gt;
    iguales_nat n p = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H1 H2.           (* n, m, p : nat&lt;br /&gt;
                                   H1 : iguales_nat n m = true&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H1. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H2. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : m = p&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  rewrite H1.                   (* iguales_nat m p = true *)&lt;br /&gt;
  rewrite H2.                   (* iguales_nat p p = true *)&lt;br /&gt;
  apply iguales_nat_refl.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.3. Definir las hipótesis sobre xs e ys para que se cumpla&lt;br /&gt;
   la propiedad &lt;br /&gt;
      desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
   y demostrarla.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* En la prueba se usará el siguiente lema *)&lt;br /&gt;
Lemma longitud_cero: forall (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = 0 -&amp;gt; xs = [].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs H.           (* X : Type&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              H : longitud xs = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs = [ ] *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              H : longitud [ ] = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    simpl in H.            (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem desempareja_empareja: forall (X : Type) (xs ys: list X),&lt;br /&gt;
    longitud xs = longitud ys -&amp;gt;&lt;br /&gt;
    desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud xs = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja xs ys) = (xs, ys) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI1]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud [ ] = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    intros ys H.                (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud [ ] = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    simpl in H.                 (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : 0 = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    symmetry in H.              (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud ys = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    apply longitud_cero in H.   (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : ys = [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [] ys) = ([], ys) *)&lt;br /&gt;
    rewrite H.                  (* desempareja (empareja [] []) = ([], []) *)&lt;br /&gt;
    simpl.                      (* ([], []) = ([], []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud [ ] -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;) -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : longitud xs&amp;#039; = longitud ys&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      apply HI1 in H1.          (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : desempareja (empareja xs&amp;#039; ys&amp;#039;) &lt;br /&gt;
                                        = (xs&amp;#039;, ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      simpl.                    (* match desempareja (empareja xs&amp;#039; ys&amp;#039;) with&lt;br /&gt;
                                   | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                   end &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      rewrite H1.               (* (x::xs&amp;#039;, y::ys&amp;#039;) = (x::xs&amp;#039;,y::ys&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.4. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
        filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
        p x = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_filtra:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
    filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
    p x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p x xs ys.           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs, ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p xs = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    simpl.                      (* [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    intros H.                   (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : [ ] = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
    destruct (p x&amp;#039;) eqn:Hx&amp;#039;. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* x&amp;#039; :: filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      rewrite H1 in Hx&amp;#039;.        (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      apply Hx&amp;#039;.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = false&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.1. Definir, por recursión, la función &lt;br /&gt;
      todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool &lt;br /&gt;
   tal que (todos p xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      todos esImpar [1;3;5;7;9]     = true&lt;br /&gt;
      todos negacion [false;false]  = true&lt;br /&gt;
      todos esPar [0;2;4;5]         = false&lt;br /&gt;
      todos (iguales_nat 5) []      = true&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then todos p xs&amp;#039;&lt;br /&gt;
             else false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (todos esImpar [1;3;5;7;9]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos negacion [false;false]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos esPar [0;2;4;5]).&lt;br /&gt;
(* = false : bool*)&lt;br /&gt;
Compute (todos (iguales_nat 5) []).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.2. Definir, por recursión, la función &lt;br /&gt;
      existe      &lt;br /&gt;
   tal que (existe p xs) se verifica si algún elemento de xs cumple&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      existe (iguales_nat 5) [0;2;3;6]           = false&lt;br /&gt;
      existe (conjuncion true) [true;true;false] = true&lt;br /&gt;
      existe esImpar [1;0;0;0;0;3]               = true&lt;br /&gt;
      existe esPar []                            = false&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint existe {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; false&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then true&lt;br /&gt;
             else existe p xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (existe (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.3. Redefinir, usando todos y negb, la función existe2 y&lt;br /&gt;
   demostrar su equivalencia con existe.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition existe2 {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  negacion (todos (fun y =&amp;gt; negacion (p y)) xs).&lt;br /&gt;
&lt;br /&gt;
Compute (existe2 (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe2 (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
Theorem equiv_existe: forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    existe p xs = existe2 p xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.               (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p xs = existe2 p xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p [ ] = existe2 p [ ] *)&lt;br /&gt;
    unfold existe2.            (* existe p [ ] = &lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                   [ ]) *)&lt;br /&gt;
    simpl.                     (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
    destruct (p x) eqn:Hx.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                  (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* true =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion true &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = false&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) &lt;br /&gt;
                                          (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion false &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      rewrite HI.              (* existe2 p xs&amp;#039; = &lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Resumen de tácticas básicas == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* Las tácticas básicas utilizadas hasta ahora son&lt;br /&gt;
  + apply H: &lt;br /&gt;
    + si el objetivo coincide con la hipótesis H, lo demuestra;&lt;br /&gt;
    + si H es una implicación,&lt;br /&gt;
      + si el objetivo coincide con la conclusión de H, lo sustituye por&lt;br /&gt;
        su premisa y&lt;br /&gt;
      + si el objetivo coincide con la premisa de H, lo sustituye por&lt;br /&gt;
        su conclusión.&lt;br /&gt;
&lt;br /&gt;
  + apply ... with ...: Especifica los valores de las variables que no&lt;br /&gt;
    se pueden deducir por emparejamiento.&lt;br /&gt;
&lt;br /&gt;
  + apply H1 in H2: Aplica la igualdad de la hipótesis H1 a la&lt;br /&gt;
    hipótesis H2.&lt;br /&gt;
&lt;br /&gt;
  + assert (H: P): Incluyed la demostración de la propiedad P y continúa&lt;br /&gt;
    la demostración añadiendo como premisa la propiedad P con nombre H. &lt;br /&gt;
&lt;br /&gt;
  + destruct b: Distingue dos casos según que b sea True o False.&lt;br /&gt;
&lt;br /&gt;
  + destruct n as [| n1]: Distingue dos casos según que n sea 0 o sea S n1. &lt;br /&gt;
&lt;br /&gt;
  + destruct p as [n m]: Sustituye el par p por (n,m).&lt;br /&gt;
&lt;br /&gt;
  + destruct e eqn: H: Distingue casos según el valor de la expresión&lt;br /&gt;
    e y lo añade al contexto la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + generalize dependent x: Mueve la variable x (y las que dependan de&lt;br /&gt;
    ella) del contexto a una hipótesis explícita en el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + induction n as [|n1 IHn1]: Inicia una demostración por inducción&lt;br /&gt;
    sobre n. El caso base en ~n  0~. El paso de la inducción consiste en&lt;br /&gt;
    suponer la propiedad para ~n1~ y demostrarla para ~S n1~. El nombre de la&lt;br /&gt;
    hipótesis de inducción es ~IHn1~.&lt;br /&gt;
&lt;br /&gt;
  + intros vars: Introduce las variables del cuantificador universal y,&lt;br /&gt;
    como premisas, los antecedentes de las implicaciones.&lt;br /&gt;
&lt;br /&gt;
  + inversion: Aplica qe los constructores son disjuntos e inyectivos. &lt;br /&gt;
&lt;br /&gt;
  + reflexivity: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
&lt;br /&gt;
  + rewrite H: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
&lt;br /&gt;
  + rewrite &amp;lt;-H: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
  + simpl: Simplifica el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + simpl in H: Simplifica la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + symmetry: Cambia un objetivo de la forma s = t en t = s.&lt;br /&gt;
&lt;br /&gt;
  + symmetry in H: Cambia la hipótesis H de la forma ~st~ en ~ts~.&lt;br /&gt;
&lt;br /&gt;
  + unfold f Expande la definición de la función f.&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Tactics.html More basic tactics] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=74</id>
		<title>Tema 5: Tácticas básicas de Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=74"/>
		<updated>2018-08-20T10:58:11Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se amplían las tácticas básicas estudiadas en los temas anteriores. Al final de la teoría se incluye un resumen de todas las tácticas usadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T5_Tacticas.v|T5_Tacticas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T5: Tácticas básicas de Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T4_PolimorfismoyOS.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   5. Control de la hipótesis de inducción  &lt;br /&gt;
   6. Expansión de definiciones &lt;br /&gt;
   7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   8. Ejercicios &lt;br /&gt;
   9. Resumen de tácticas básicas &lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== La táctica &amp;#039;apply&amp;#039; == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que &lt;br /&gt;
          n = m  -&amp;gt;&lt;br /&gt;
          [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
          [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración sin apply *)&lt;br /&gt;
Theorem artificial_1a : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  rewrite H2.           (* [n; p] = [n; p] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* Demostración con apply *)&lt;br /&gt;
Theorem artificial_1b : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que &lt;br /&gt;
      n = m  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
      [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2 : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : forall q r : nat, q = r -&amp;gt; [q; o] = [r; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  apply H2.             (* n = m *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039; en hipótesis condicionales y&lt;br /&gt;
   razonamiento hacia atrás&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Demostrar que &lt;br /&gt;
      (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
      [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2a : forall (n m : nat),&lt;br /&gt;
    (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H1 H2. (* n, m : nat&lt;br /&gt;
                       H1 : (n, n) = (m, m)&lt;br /&gt;
                       H2 : forall q r : nat, (q, q) = (r, r) -&amp;gt; [q] = [r]&lt;br /&gt;
                       ============================&lt;br /&gt;
                       [n] = [m] *)&lt;br /&gt;
  apply H2.         (* (n, n) = (m, m) *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar, sin usar simpl, que&lt;br /&gt;
      (forall n, evenb n = true -&amp;gt; oddb (S n) = true) -&amp;gt;&lt;br /&gt;
      evenb 3 = true -&amp;gt;&lt;br /&gt;
      oddb 4 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial_ex :&lt;br /&gt;
  (forall n, esPar n = true -&amp;gt; esImpar (S n) = true) -&amp;gt;&lt;br /&gt;
  esPar 3 = true -&amp;gt;&lt;br /&gt;
  esImpar 4 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 H2. (* H1 : forall n : nat, esPar n = true -&amp;gt; esImpar (S n) = true&lt;br /&gt;
                   H2 : esPar 3 = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   esImpar 4 = true *)&lt;br /&gt;
  apply H1.     (* esPar 3 = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Demostrar que &lt;br /&gt;
      true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
      iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3a: forall (n : nat),&lt;br /&gt;
    true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
    iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H. (* n : nat&lt;br /&gt;
                 H : true = iguales_nat n 5&lt;br /&gt;
                 ============================&lt;br /&gt;
                 iguales_nat (S (S n)) 7 = true *)&lt;br /&gt;
  symmetry.   (* true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  simpl.      (* true = iguales_nat n 5 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Necesidad de usar symmetry antes de apply.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar&lt;br /&gt;
      forall (xs ys : list nat), &lt;br /&gt;
       xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa2: forall (xs ys : list nat),&lt;br /&gt;
    xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.           (* xs, ys : list nat&lt;br /&gt;
                               H : xs = inversa ys&lt;br /&gt;
                               ============================&lt;br /&gt;
                               ys = inversa xs *)&lt;br /&gt;
  rewrite H.                (* ys = inversa (inversa ys) *)&lt;br /&gt;
  symmetry.                 (* inversa (inversa ys) = ys *)&lt;br /&gt;
  apply inversa_involutiva. &lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== La táctica &amp;#039;apply ... with ...&amp;#039; == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall (a b c d e f : nat),&lt;br /&gt;
       [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
       [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
       [a;b] = [e;f].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejemplo_con_transitiva: forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2. (* a, b, c, d, e, f : nat&lt;br /&gt;
                               H1 : [a; b] = [c; d]&lt;br /&gt;
                               H2 : [c; d] = [e; f]&lt;br /&gt;
                               ============================&lt;br /&gt;
                               [a; b] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H1.             (* [c; d] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H2.             (* [e; f] = [e; f] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem igualdad_transitiva: forall (X:Type) (n m o : X),&lt;br /&gt;
    n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X n m o H1 H2. (* X : Type&lt;br /&gt;
                           n, m, o : X&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : m = o&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.         (* m = o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.         (* o = o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El ejercicio 2.2 es una generalización del 2.1, sus&lt;br /&gt;
   demostraciones son isomorfas y se puede usar el 2.2 en la&lt;br /&gt;
   demostración del 2.1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.                  (* a, b, c, d, e, f : nat&lt;br /&gt;
                                                H1 : [a; b] = [c; d]&lt;br /&gt;
                                                H2 : [c; d] = [e; f]&lt;br /&gt;
                                                ============================&lt;br /&gt;
                                                [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with (m:=[c;d]).&lt;br /&gt;
  -                                          (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                          (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039;&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.             (* a, b, c, d, e, f : nat&lt;br /&gt;
                                           H1 : [a; b] = [c; d]&lt;br /&gt;
                                           H2 : [c; d] = [e; f]&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with [c;d].&lt;br /&gt;
  -                                     (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                     (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply ... whith ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1. Demostrar que&lt;br /&gt;
      forall (n m o p : nat),&lt;br /&gt;
        m = (menosDos o) -&amp;gt;&lt;br /&gt;
        (n + p) = m -&amp;gt;&lt;br /&gt;
        (n + p) = (menosDos o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_igualdad_transitiva: forall (n m o p : nat),&lt;br /&gt;
    m = (menosDos o) -&amp;gt;&lt;br /&gt;
    (n + p) = m -&amp;gt;&lt;br /&gt;
    (n + p) = (menosDos o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2.             (* n, m, o, p : nat&lt;br /&gt;
                                       H1 : m = menosDos o&lt;br /&gt;
                                       H2 : n + p = m&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n + p = menosDos o *)&lt;br /&gt;
  apply igualdad_transitiva with m. &lt;br /&gt;
  -                                 (* n + p = m *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
  -                                 (* m = menosDos o *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== La táctica &amp;#039;inversion&amp;#039; == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       S n = S m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inyectiva: forall (n m : nat),&lt;br /&gt;
  S n = S m -&amp;gt;&lt;br /&gt;
  n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (n m o : nat),&lt;br /&gt;
       [n; m] = [o; o] -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej1: forall (n m o : nat),&lt;br /&gt;
    [n; m] = [o; o] -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H. (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [n] = [m] *)&lt;br /&gt;
  inversion H.    (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     H1 : n = o&lt;br /&gt;
                     H2 : m = o&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [o] = [o] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       [n] = [m] -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej2: forall (n m : nat),&lt;br /&gt;
    [n] = [m] -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.         (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = m *)&lt;br /&gt;
  inversion H as [Hnm]. (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           Hnm : n = m&lt;br /&gt;
                           ============================&lt;br /&gt;
                           m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Nombramiento de las hipótesis generadas por inversión.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
        x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej3 : forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
  x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
  y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
  x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H1 H2. (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x = y *)&lt;br /&gt;
  inversion H1.               (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = y *)&lt;br /&gt;
  inversion H2.               (* xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 H4 : y = x&lt;br /&gt;
                                 H5 : xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = x *)&lt;br /&gt;
  symmetry.                   (* x = z *)&lt;br /&gt;
  apply H0.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.4. Demostrar que&lt;br /&gt;
      forall n:nat,&lt;br /&gt;
       iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_0_n: forall n:nat,&lt;br /&gt;
    iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 n = true -&amp;gt; n = 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
    intros H.           (* H : iguales_nat 0 0 = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 (S n&amp;#039;) = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    intros H.           (* n&amp;#039; : nat&lt;br /&gt;
                           H : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           S n&amp;#039; = 0 *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.5. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       S n = O -&amp;gt; 2 + 2 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej4: forall (n : nat),&lt;br /&gt;
    S n = O -&amp;gt;&lt;br /&gt;
    2 + 2 = 5.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.  (* n : nat&lt;br /&gt;
                  H : S n = 0&lt;br /&gt;
                  ============================&lt;br /&gt;
                  2 + 2 = 5 *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.6. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       false = true -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej5: forall (n m : nat),&lt;br /&gt;
    false = true -&amp;gt; [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : false = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   [n] = [m] *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
        y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        x = z.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej6 :&lt;br /&gt;
  forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
    x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
    y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
    x = z.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H. (* X : Type&lt;br /&gt;
                             x, y, z : X&lt;br /&gt;
                             xs, ys : list X&lt;br /&gt;
                             H : x :: y :: xs = [ ]&lt;br /&gt;
                             ============================&lt;br /&gt;
                             y :: xs = z :: ys -&amp;gt; x = z *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.  &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.7. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
       x = y -&amp;gt; f x = f y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem funcional: forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
    x = y -&amp;gt; f x = f y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f x y H. (* A : Type&lt;br /&gt;
                         B : Type&lt;br /&gt;
                         f : A -&amp;gt; B&lt;br /&gt;
                         x, y : A&lt;br /&gt;
                         H : x = y&lt;br /&gt;
                         ============================&lt;br /&gt;
                         f x = f y *)&lt;br /&gt;
  rewrite H.          (* f y = f y *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Uso de tácticas sobre las hipótesis == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n m : nat) (b : bool),&lt;br /&gt;
       iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
       iguales_nat n m = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inj: forall (n m : nat) (b : bool),&lt;br /&gt;
    iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
    iguales_nat n m = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m b H. (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat (S n) (S m) = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  simpl in H.     (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat n m = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de táctica &amp;#039;simpl in ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
       true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
       true = iguales_nat (S (S n)) 7.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3&amp;#039;: forall (n : nat),&lt;br /&gt;
  (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
  true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
  true = iguales_nat (S (S n)) 7.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H1 H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat n 5&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat n 5 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H1 in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat (S (S n)) 7&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de las tácticas &amp;#039;apply H1 in H2&amp;#039; y &amp;#039;symemetry in H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n + n = m + m -&amp;gt;&lt;br /&gt;
        n = m.&lt;br /&gt;
&lt;br /&gt;
   Nota: Usar suma_s_Sm.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_n_inyectiva:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    n + n = m + m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, n + n = m + m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI]. &lt;br /&gt;
  -                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, 0 + 0 = m + m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H1.                 (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* H1 : 0 + 0 = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = S m *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, S n&amp;#039; + S n&amp;#039; = m + m &lt;br /&gt;
                                                    -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H2.                 (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H2.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H2.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : n&amp;#039; + S n&amp;#039; = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (n&amp;#039; + n&amp;#039;) = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H0.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : m + S m = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H0.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : m + m = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      apply HI in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- H1.             (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Control de la hipótesis de inducción == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª intento *)&lt;br /&gt;
Theorem doble_inyectiva_FAILED : forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.             (* n, m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros H.             (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble (S n&amp;#039;) = doble m -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros H.             (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva: forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H.           (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble (S n&amp;#039;) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, S (S (doble n&amp;#039;)) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H.           (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.           (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.        (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la estrategia de generalización.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_true : forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat 0 m = true &lt;br /&gt;
                                              -&amp;gt; 0 = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 (S m&amp;#039;) = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat (S n&amp;#039;) m = true&lt;br /&gt;
                                                   -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) 0 = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                        -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) (S m&amp;#039;) = true &lt;br /&gt;
                                   -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* iguales_nat n&amp;#039; m&amp;#039; = true -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : iguales_nat n&amp;#039; m&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply HIn&amp;#039; in H.          (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      rewrite H.                (* S m&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
    &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2a: forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI].&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                      (* doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros H.                   (* n : nat&lt;br /&gt;
                                   H : doble n = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                           (* H : doble 0 = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.               (* n&amp;#039; : nat&lt;br /&gt;
                                   H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble (S m&amp;#039;) -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
&lt;br /&gt;
    intros H.                   (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.               (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble (S n&amp;#039;) = doble m&amp;#039; -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.          (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2 : forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.               (* n, m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  generalize dependent n.   (* m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI]. &lt;br /&gt;
  -                         (*  &lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                  (* forall n : nat, doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros n H.             (* n : nat&lt;br /&gt;
                               H : doble n = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                       (* H : doble 0 = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                       (* n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.           (* n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                         (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble (S m&amp;#039;) &lt;br /&gt;
                                               -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
    intros n H.             (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n : nat&lt;br /&gt;
                               H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.      (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.             (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.          (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;generalize dependent n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Demostrar que&lt;br /&gt;
      forall x y : id,&lt;br /&gt;
       iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_true: forall x y : id,&lt;br /&gt;
  iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [m] [n].           (* m, n : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id (Id m) (Id n) = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  simpl.                    (* iguales_nat m n = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  intros H.                 (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
  assert (H&amp;#039; : m = n).&lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               m = n *)&lt;br /&gt;
    apply iguales_nat_true. (* iguales_nat m n = true *)&lt;br /&gt;
    apply H. &lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               H&amp;#039; : m = n&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
    rewrite H&amp;#039;.             (* Id n = Id n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar, por inducción sobre l,&lt;br /&gt;
      forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
        longitud xs = n -&amp;gt;&lt;br /&gt;
        nthOpcional xs n = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nthOpcional_None: forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = n -&amp;gt;&lt;br /&gt;
    nthOpcional xs n = None.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n X xs.               (* n : nat&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  generalize dependent n.       (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud [] = n -&amp;gt; nthOpcional [] n = None *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = n -&amp;gt; &lt;br /&gt;
                                   nthOpcional (x :: xs&amp;#039;) n = None *)&lt;br /&gt;
    destruct n as [|n&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = 0 -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) (S n&amp;#039;) = None *)&lt;br /&gt;
      simpl.                    (* S (longitud xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                   nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      apply HI.                 (* longitud xs&amp;#039; = n&amp;#039; *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  H1 : longitud xs&amp;#039; = n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs&amp;#039; = longitud xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Expansión de definiciones == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.1. Definir la función&lt;br /&gt;
      cuadrado : nata -&amp;gt; nat&lt;br /&gt;
   tal que (cuadrado n) es el cuadrado de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition cuadrado (n:nat) : nat := n * n.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuadrado_mult : forall n m : nat,&lt;br /&gt;
    cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                            (* n, m : nat&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            cuadrado (n * m) = &lt;br /&gt;
                                            cuadrado n * cuadrado m *)&lt;br /&gt;
  unfold cuadrado.                       (* (n * m) * (n * m) = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  rewrite producto_asociativa.           (* ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  assert (H : (n * m) * n = (n * n) * m). &lt;br /&gt;
  -                                      (* (n * m) * n = (n * n) * m) *)&lt;br /&gt;
    rewrite producto_conmutativa.        (* n * (n * m) = (n * n) * m *)&lt;br /&gt;
    apply producto_asociativa.           &lt;br /&gt;
  -                                      (* n, m : nat&lt;br /&gt;
                                            H : (n * m) * n = (n * n) * m&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite H.                           (* ((n * n) * m) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite producto_asociativa.         (* ((n * n) * m) * m = &lt;br /&gt;
                                            ((n * n) * m) * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;unfold&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.4. Definir la función&lt;br /&gt;
      const5 : nat -&amp;gt; nat&lt;br /&gt;
   tal que (const5 x) es el número 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5 (x: nat) : nat := 5.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.5. Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact prop_const5 : forall m : nat,&lt;br /&gt;
    const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.    (* m : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  const5 m + 1 = const5 (m + 1) + 1 *)&lt;br /&gt;
  simpl.       (* 6 = 6 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Expansión automática de la definición de const5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.6. Se coonsidera la siguiente definición&lt;br /&gt;
      Definition const5b (x:nat) : nat :=&lt;br /&gt;
        match x with&lt;br /&gt;
        | O   =&amp;gt; 5&lt;br /&gt;
        | S _ =&amp;gt; 5&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5b (x:nat) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | O   =&amp;gt; 5&lt;br /&gt;
  | S _ =&amp;gt; 5&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fact prop_const5b_1: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m. (* m : nat&lt;br /&gt;
               ============================&lt;br /&gt;
               const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  simpl.    (* const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Fact prop_const5b_2: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.      (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b 0 + 1 = const5b (0 + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b (S m) + 1 = const5b (S m + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Fact prop_const5b_3: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.       (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  unfold const5b. (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     match m with&lt;br /&gt;
                     | 0 | _ =&amp;gt; 5&lt;br /&gt;
                     end + 1 = match m + 1 with&lt;br /&gt;
                               | 0 | _ =&amp;gt; 5&lt;br /&gt;
                               end + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -               (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match 0 + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match S m + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.1. Se considera la siguiente definición &lt;br /&gt;
      Definition const_false (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then false&lt;br /&gt;
        else if iguales_nat n 5 then false&lt;br /&gt;
        else                         false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       const_false n = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const_false (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then false&lt;br /&gt;
  else if iguales_nat n 5 then false&lt;br /&gt;
  else                         false.&lt;br /&gt;
&lt;br /&gt;
Theorem const_false_false : forall n : nat,&lt;br /&gt;
    const_false n = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                     (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   const_false n = false *)&lt;br /&gt;
  unfold const_false.           (* (if iguales_nat n 3 then false &lt;br /&gt;
                                   else if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) =&lt;br /&gt;
                                   false *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) = false *)&lt;br /&gt;
    destruct (iguales_nat n 5). &lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.2. Se considera la siguiente definición &lt;br /&gt;
      Definition ej (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then true&lt;br /&gt;
        else if iguales_nat n 5 then true&lt;br /&gt;
        else                     false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       ej n = true -&amp;gt; esImpar n = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ej (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then true&lt;br /&gt;
  else if iguales_nat n 5 then true&lt;br /&gt;
  else                     false.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem ej_impar_a: forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                       (* n : nat&lt;br /&gt;
                                       H : ej n = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       esImpar n = true *)&lt;br /&gt;
  unfold ej in H. (* n : nat&lt;br /&gt;
                                      H : (if iguales_nat n 3&lt;br /&gt;
                                           then true&lt;br /&gt;
                                           else if iguales_nat n 5 &lt;br /&gt;
                                                then true &lt;br /&gt;
                                                else false) &lt;br /&gt;
                                          = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                                (* n : nat&lt;br /&gt;
                                      H : true = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem ej_impar : forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                             (* n : nat&lt;br /&gt;
                                             H : ej n = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  unfold ej in H.                         (* n : nat&lt;br /&gt;
                                             H : (if iguales_nat n 3&lt;br /&gt;
                                                  then true&lt;br /&gt;
                                                  else if iguales_nat n 5 &lt;br /&gt;
                                                       then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3) eqn: H3.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    apply iguales_nat_true in H3.         (* n : nat&lt;br /&gt;
                                             H3 : n = 3&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    rewrite H3.                           (* esImpar 3 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H : (if iguales_nat n 5 &lt;br /&gt;
                                                  then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    destruct (iguales_nat n 5) eqn:H5. &lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      apply iguales_nat_true in H5.       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : n = 5&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      rewrite H5.                         (* esImpar 5 = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = false&lt;br /&gt;
                                             H : false = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct e eqn: H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.1. Demostrar que desempareja y empareja son inversas; es decir,&lt;br /&gt;
        forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
          desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
          empareja xs ys = ps.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem empareja_desempareja: forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
    desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
    empareja xs ys = ps.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y ps.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ps : list (X * Y)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ps = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = ps *)&lt;br /&gt;
  induction ps as [|(x,y) ps&amp;#039; HI].&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja [ ] = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = [ ] *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja [ ] = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          H1 : [ ] = xs&lt;br /&gt;
                                          H2 : [ ] = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja [ ] [ ] = [ ] *)&lt;br /&gt;
    simpl.                             (* [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) &lt;br /&gt;
                                               -&amp;gt; empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ((x,y)::ps&amp;#039;) = (xs,ys) &lt;br /&gt;
                                           -&amp;gt; empareja xs ys = (x,y)::ps&amp;#039; *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    destruct (desempareja ps&amp;#039;) eqn: E. (* Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs: ist X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : match desempareja ps&amp;#039; with&lt;br /&gt;
                                              | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                              end = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite E in H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja (x :: l) (y :: l0) = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl.                             (* (x, y) :: empareja l l0 = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite HI.&lt;br /&gt;
    +                                  (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (x, y) :: ps&amp;#039; = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                  (*   X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (l, l0) = (l, l0)&lt;br /&gt;
 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.2. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
        f (f (f b)) = f b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem bool_tres_veces:&lt;br /&gt;
  forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
    f (f (f b)) = f b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f b.                    (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f b)) = f b *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f true)) = f true *)&lt;br /&gt;
    destruct (f true) eqn:H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      rewrite H1.                (* f true = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      destruct (f false) eqn:H2. &lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = false *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = false *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f false)) = f false *)&lt;br /&gt;
    destruct (f false) eqn:H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      destruct (f true) eqn:H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = true *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      rewrite H3.                (* f false = false *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ejercicios == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        iguales_nat n m = iguales_nat m n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_simetrica: forall n m : nat,&lt;br /&gt;
    iguales_nat n m = iguales_nat m n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                          (* n, m : nat&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          iguales_nat n m = iguales_nat m n *)&lt;br /&gt;
  destruct (iguales_nat n m) eqn:H1.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    apply iguales_nat_true in H1.      (* n, m : nat&lt;br /&gt;
                                          H1 : n = m&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    rewrite H1.                        (* true = iguales_nat m m *)&lt;br /&gt;
    symmetry.                          (* iguales_nat m m = true *)&lt;br /&gt;
    apply iguales_nat_refl.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = iguales_nat m n *)&lt;br /&gt;
    destruct (iguales_nat m n) eqn:H2. &lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      apply iguales_nat_true in H2.    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite H2 in H1.                (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n n = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite iguales_nat_refl in H1.  (* n, m : nat&lt;br /&gt;
                                          H1 : true = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.2. Demostrar que&lt;br /&gt;
        forall n m p : nat,&lt;br /&gt;
          iguales_nat n m = true -&amp;gt;&lt;br /&gt;
          iguales_nat m p = true -&amp;gt;&lt;br /&gt;
          iguales_nat n p = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_trans: forall n m p : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt;&lt;br /&gt;
    iguales_nat m p = true -&amp;gt;&lt;br /&gt;
    iguales_nat n p = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H1 H2.           (* n, m, p : nat&lt;br /&gt;
                                   H1 : iguales_nat n m = true&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H1. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H2. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : m = p&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  rewrite H1.                   (* iguales_nat m p = true *)&lt;br /&gt;
  rewrite H2.                   (* iguales_nat p p = true *)&lt;br /&gt;
  apply iguales_nat_refl.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.3. Definir las hipótesis sobre xs e ys para que se cumpla&lt;br /&gt;
   la propiedad &lt;br /&gt;
      desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
   y demostrarla.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* En la prueba se usará el siguiente lema *)&lt;br /&gt;
Lemma longitud_cero: forall (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = 0 -&amp;gt; xs = [].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs H.           (* X : Type&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              H : longitud xs = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs = [ ] *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              H : longitud [ ] = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    simpl in H.            (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem desempareja_empareja: forall (X : Type) (xs ys: list X),&lt;br /&gt;
    longitud xs = longitud ys -&amp;gt;&lt;br /&gt;
    desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud xs = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja xs ys) = (xs, ys) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI1]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud [ ] = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    intros ys H.                (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud [ ] = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    simpl in H.                 (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : 0 = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    symmetry in H.              (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud ys = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    apply longitud_cero in H.   (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : ys = [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [] ys) = ([], ys) *)&lt;br /&gt;
    rewrite H.                  (* desempareja (empareja [] []) = ([], []) *)&lt;br /&gt;
    simpl.                      (* ([], []) = ([], []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud [ ] -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;) -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : longitud xs&amp;#039; = longitud ys&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      apply HI1 in H1.          (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : desempareja (empareja xs&amp;#039; ys&amp;#039;) &lt;br /&gt;
                                        = (xs&amp;#039;, ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      simpl.                    (* match desempareja (empareja xs&amp;#039; ys&amp;#039;) with&lt;br /&gt;
                                   | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                   end &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      rewrite H1.               (* (x::xs&amp;#039;, y::ys&amp;#039;) = (x::xs&amp;#039;,y::ys&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.4. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
        filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
        p x = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_filtra:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
    filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
    p x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p x xs ys.           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs, ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p xs = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    simpl.                      (* [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    intros H.                   (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : [ ] = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
    destruct (p x&amp;#039;) eqn:Hx&amp;#039;. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* x&amp;#039; :: filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      rewrite H1 in Hx&amp;#039;.        (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      apply Hx&amp;#039;.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = false&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.1. Definir, por recursión, la función &lt;br /&gt;
      todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool &lt;br /&gt;
   tal que (todos p xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      todos esImpar [1;3;5;7;9]     = true&lt;br /&gt;
      todos negacion [false;false]  = true&lt;br /&gt;
      todos esPar [0;2;4;5]         = false&lt;br /&gt;
      todos (iguales_nat 5) []      = true&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then todos p xs&amp;#039;&lt;br /&gt;
             else false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (todos esImpar [1;3;5;7;9]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos negacion [false;false]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos esPar [0;2;4;5]).&lt;br /&gt;
(* = false : bool*)&lt;br /&gt;
Compute (todos (iguales_nat 5) []).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.2. Definir, por recursión, la función &lt;br /&gt;
      existe      &lt;br /&gt;
   tal que (existe p xs) se verifica si algún elemento de xs cumple&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      existe (iguales_nat 5) [0;2;3;6]           = false&lt;br /&gt;
      existe (conjuncion true) [true;true;false] = true&lt;br /&gt;
      existe esImpar [1;0;0;0;0;3]               = true&lt;br /&gt;
      existe esPar []                            = false&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint existe {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; false&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then true&lt;br /&gt;
             else existe p xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (existe (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.3. Redefinir, usando todos y negb, la función existe2 y&lt;br /&gt;
   demostrar su equivalencia con existe.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition existe2 {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  negacion (todos (fun y =&amp;gt; negacion (p y)) xs).&lt;br /&gt;
&lt;br /&gt;
Compute (existe2 (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe2 (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
Theorem equiv_existe: forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    existe p xs = existe2 p xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.               (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p xs = existe2 p xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p [ ] = existe2 p [ ] *)&lt;br /&gt;
    unfold existe2.            (* existe p [ ] = &lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                   [ ]) *)&lt;br /&gt;
    simpl.                     (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
    destruct (p x) eqn:Hx.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                  (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* true =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion true &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = false&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) &lt;br /&gt;
                                          (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion false &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      rewrite HI.              (* existe2 p xs&amp;#039; = &lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 9. Resumen de tácticas básicas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* Las tácticas básicas utilizadas hasta ahora son&lt;br /&gt;
  + apply H: &lt;br /&gt;
    + si el objetivo coincide con la hipótesis H, lo demuestra;&lt;br /&gt;
    + si H es una implicación,&lt;br /&gt;
      + si el objetivo coincide con la conclusión de H, lo sustituye por&lt;br /&gt;
        su premisa y&lt;br /&gt;
      + si el objetivo coincide con la premisa de H, lo sustituye por&lt;br /&gt;
        su conclusión.&lt;br /&gt;
&lt;br /&gt;
  + apply ... with ...: Especifica los valores de las variables que no&lt;br /&gt;
    se pueden deducir por emparejamiento.&lt;br /&gt;
&lt;br /&gt;
  + apply H1 in H2: Aplica la igualdad de la hipótesis H1 a la&lt;br /&gt;
    hipótesis H2.&lt;br /&gt;
&lt;br /&gt;
  + assert (H: P): Incluyed la demostración de la propiedad P y continúa&lt;br /&gt;
    la demostración añadiendo como premisa la propiedad P con nombre H. &lt;br /&gt;
&lt;br /&gt;
  + destruct b: Distingue dos casos según que b sea True o False.&lt;br /&gt;
&lt;br /&gt;
  + destruct n as [| n1]: Distingue dos casos según que n sea 0 o sea S n1. &lt;br /&gt;
&lt;br /&gt;
  + destruct p as [n m]: Sustituye el par p por (n,m).&lt;br /&gt;
&lt;br /&gt;
  + destruct e eqn: H: Distingue casos según el valor de la expresión&lt;br /&gt;
    e y lo añade al contexto la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + generalize dependent x: Mueve la variable x (y las que dependan de&lt;br /&gt;
    ella) del contexto a una hipótesis explícita en el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + induction n as [|n1 IHn1]: Inicia una demostración por inducción&lt;br /&gt;
    sobre n. El caso base en ~n  0~. El paso de la inducción consiste en&lt;br /&gt;
    suponer la propiedad para ~n1~ y demostrarla para ~S n1~. El nombre de la&lt;br /&gt;
    hipótesis de inducción es ~IHn1~.&lt;br /&gt;
&lt;br /&gt;
  + intros vars: Introduce las variables del cuantificador universal y,&lt;br /&gt;
    como premisas, los antecedentes de las implicaciones.&lt;br /&gt;
&lt;br /&gt;
  + inversion: Aplica qe los constructores son disjuntos e inyectivos. &lt;br /&gt;
&lt;br /&gt;
  + reflexivity: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
&lt;br /&gt;
  + rewrite H: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
&lt;br /&gt;
  + rewrite &amp;lt;-H: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
  + simpl: Simplifica el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + simpl in H: Simplifica la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + symmetry: Cambia un objetivo de la forma s = t en t = s.&lt;br /&gt;
&lt;br /&gt;
  + symmetry in H: Cambia la hipótesis H de la forma ~st~ en ~ts~.&lt;br /&gt;
&lt;br /&gt;
  + unfold f Expande la definición de la función f.&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Tactics.html More basic tactics] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_6:_L%C3%B3gica_en_Coq&amp;diff=73</id>
		<title>Tema 6: Lógica en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_6:_L%C3%B3gica_en_Coq&amp;diff=73"/>
		<updated>2018-08-20T10:52:39Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este capítulo se amplía el campo de aplicación de Coq para todas las conectivas y cuantificadores de la lógica de primer orden.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T6_Logica.v|T6_Logica.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T6: Lógica en Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T5_Tacticas.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. Introducción&lt;br /&gt;
   2. Conectivas lógicas &lt;br /&gt;
      1. Conjunción &lt;br /&gt;
      2. Disyunción  &lt;br /&gt;
      3. Falsedad y negación  &lt;br /&gt;
      4. Verdad&lt;br /&gt;
      5. Equivalencia lógica&lt;br /&gt;
      6. Cuantificación existencial  &lt;br /&gt;
   3. Programación con proposiciones &lt;br /&gt;
   4. Aplicando teoremas a argumentos &lt;br /&gt;
   5. Coq vs. teoría de conjuntos &lt;br /&gt;
      1. Extensionalidad funcional&lt;br /&gt;
      2. Proposiciones y booleanos  &lt;br /&gt;
      3. Lógica clásica vs. constructiva  &lt;br /&gt;
   Bibliografía&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 1. Introducción == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      3 = 3.&lt;br /&gt;
      3 = 4.&lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
      forall n : nat, n = 2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check 3 = 3.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check 3 = 4.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check forall n m : nat, n + m = m + n.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check forall n : nat, n = 2.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El tipo de las fórmulas es Prop.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Demostrar que 2 más dos es 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_2_y_2:&lt;br /&gt;
  2 + 2 = 4.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Usa la proposición &amp;#039;2 + 2 = 4&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la proposición &lt;br /&gt;
      prop_suma: Prop&lt;br /&gt;
   que afirma que la suma de 2 y 2 es 4. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prop_suma: Prop := 2 + 2 = 4.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Calcular el tipo de prop_suma&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check prop_suma.&lt;br /&gt;
(* ===&amp;gt; prop_suma : Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Usando prop_suma, demostrar que la suma de 2 y 2 es 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_suma_es_verdadera:&lt;br /&gt;
  prop_suma.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Definir la proposición &lt;br /&gt;
      es_tres (n : nat) : Prop&lt;br /&gt;
   tal que (es_tres n) se verifica si n es el número 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition es_tres (n : nat) : Prop :=&lt;br /&gt;
  n = 3.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.2. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      es_tres.&lt;br /&gt;
      es_tres 3.&lt;br /&gt;
      es_tres 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres.&lt;br /&gt;
(* ===&amp;gt; nat -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres 3.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres 5.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Ejemplo de proposición parametrizada.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir la función&lt;br /&gt;
      inyectiva {A B : Type} (f : A -&amp;gt; B) : Prop :=&lt;br /&gt;
   tal que (inyectiva f) se verifica si f es inyectiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition inyectiva {A B : Type} (f : A -&amp;gt; B) : Prop :=&lt;br /&gt;
  forall x y : A, f x = f y -&amp;gt; x = y.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Demostrar que la funcion sucesor es inyectiva; es&lt;br /&gt;
   decir, &lt;br /&gt;
      inyectiva S.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma suc_iny: inyectiva S.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5. Calcular los tipos de las siguientes expresiones&lt;br /&gt;
      3 = 5.&lt;br /&gt;
      eq 3 5.&lt;br /&gt;
      eq 3.&lt;br /&gt;
      @eq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (3 = 5).&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check (eq 3 5).&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check (eq 3).&lt;br /&gt;
(* ===&amp;gt; nat -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check @eq.&lt;br /&gt;
(* ===&amp;gt; forall A : Type, A -&amp;gt; A -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. La expresión (x = y) es una abreviatura de (eq x y).&lt;br /&gt;
   2. Se escribe @eq en lugar de eq para ver los argumentos implícitos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conectivas lógicas == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.1. Conjunción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que&lt;br /&gt;
      3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ej_conjuncion: 3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.         &lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    3 + 4 = 7 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    2 * 2 = 4 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. El símbolo de conjunción se escribe con /\&lt;br /&gt;
   2. La táctica &amp;#039;split&amp;#039; sustituye el objetivo (P /\ Q) por los&lt;br /&gt;
   subobjetivos P y Q. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que&lt;br /&gt;
      forall A B : Prop, A -&amp;gt; B -&amp;gt; A /\ B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_intro: forall A B : Prop, A -&amp;gt; B -&amp;gt; A /\ B.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B HA HB. (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       A /\ B *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                 (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       A *)&lt;br /&gt;
    apply HA.&lt;br /&gt;
  -                 (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       B *)&lt;br /&gt;
    apply HB.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar, con con_intro, que&lt;br /&gt;
      3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ej_conjuncion&amp;#039;: 3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply conj_intro. &lt;br /&gt;
  -                 (* 3 + 4 = 7 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* 2 * 2 = 4 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.1. Demostrar que&lt;br /&gt;
      forall n m : nat, n + m = 0 -&amp;gt; n = 0 /\ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_conj:&lt;br /&gt;
  forall n m : nat, n + m = 0 -&amp;gt; n = 0 /\ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.                      (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        n = 0 /\ m = 0 *)&lt;br /&gt;
  apply conj_intro.&lt;br /&gt;
  -                                  (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        n = 0 *)&lt;br /&gt;
    destruct n.&lt;br /&gt;
    +                                (* m : nat&lt;br /&gt;
                                        H : 0 + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                (* n, m : nat&lt;br /&gt;
                                        H : S n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S n = 0 *)&lt;br /&gt;
      simpl in H.                    (* n, m : nat&lt;br /&gt;
                                        H : S (n + m) = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S n = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                                  (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        m = 0 *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                                (* n : nat&lt;br /&gt;
                                        H : n + 0 = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                (* n, m : nat&lt;br /&gt;
                                        H : n + S m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      rewrite suma_conmutativa in H. (* n, m : nat&lt;br /&gt;
                                        H : S m + n = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      simpl in H.                    (* n, m : nat&lt;br /&gt;
                                        H : S (m + n) = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.4. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2 :&lt;br /&gt;
  forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.          (* n, m : nat&lt;br /&gt;
                            H : n = 0 /\ m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  destruct H as [Hn Hm]. (* n, m : nat&lt;br /&gt;
                            Hn : n = 0&lt;br /&gt;
                            Hm : m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  rewrite Hn.            (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.            (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct H as [HA HB]&amp;#039; que  sustituye la&lt;br /&gt;
   hipótesis H de la forma (A /\ B) por las hipótesis HA (que afirma&lt;br /&gt;
   que A es verdad) y HB (que afirma que B es verdad).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.5. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2&amp;#039; :&lt;br /&gt;
  forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m [Hn Hm].    (* n, m : nat&lt;br /&gt;
                            Hn : n = 0&lt;br /&gt;
                            Hm : m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  rewrite Hn.            (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.            (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;intros x [HA HB]&amp;#039;, cuando el objetivo es de la&lt;br /&gt;
   forma (forall x, A /\ B -&amp;gt; C), introduce la variable x y las&lt;br /&gt;
   hipótesis HA y HB afirmando la certeza de A y de B, respectivamente.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.6. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 -&amp;gt; m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2&amp;#039;&amp;#039; :&lt;br /&gt;
  forall n m : nat, n = 0 -&amp;gt; m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m Hn Hm. (* n, m : nat&lt;br /&gt;
                       Hn : n = 0&lt;br /&gt;
                       Hm : m = 0&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n + m = 0 *)&lt;br /&gt;
  rewrite Hn.       (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.       (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.7. Demostrar que&lt;br /&gt;
      forall n m : nat, n + m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion3 :&lt;br /&gt;
  forall n m : nat, n + m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.                (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
  assert (H&amp;#039; : n = 0 /\ m = 0). &lt;br /&gt;
  -                            (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n = 0 /\ m = 0 *)&lt;br /&gt;
    apply ejercicio_conj.      (* n + m = 0 *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                            (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  H&amp;#039; : n = 0 /\ m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
    destruct H&amp;#039; as [Hn Hm].    (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  Hn : n = 0&lt;br /&gt;
                                  Hm : m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
    rewrite Hn.                (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.8. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_e1 : forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         P *)&lt;br /&gt;
  apply HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.2. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_e2: forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; Q.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q *)&lt;br /&gt;
  apply HQ.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.9. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; Q /\ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conj_conmutativa: forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; Q /\ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q /\ P *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                   (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q *)&lt;br /&gt;
    apply HQ.&lt;br /&gt;
  -                   (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.3. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        P /\ (Q /\ R) -&amp;gt; (P /\ Q) /\ R.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conj_asociativa : forall P Q R : Prop,&lt;br /&gt;
  P /\ (Q /\ R) -&amp;gt; (P /\ Q) /\ R.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R [HP [HQ HR]]. (* P, Q, R : Prop&lt;br /&gt;
                                HP : P&lt;br /&gt;
                                HQ : Q&lt;br /&gt;
                                HR : R&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (P /\ Q) /\ R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                          (* P /\ Q *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                        (* P *)&lt;br /&gt;
      apply HP.&lt;br /&gt;
    +                        (* Q *)&lt;br /&gt;
      apply HQ.&lt;br /&gt;
  -                          (* R *)&lt;br /&gt;
    apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;intros P Q R [HP [HQ HR]]&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.10. Calcular el tipo de la expresión&lt;br /&gt;
      and&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check and.&lt;br /&gt;
(* ===&amp;gt; and : Prop -&amp;gt; Prop -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. (x /\ y) es una abreviatura de (and x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.2. Disyunción  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Lemma disy_ej1:&lt;br /&gt;
  forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.&lt;br /&gt;
  destruct H as [Hn | Hm]. &lt;br /&gt;
  -                        (* n, m : nat&lt;br /&gt;
                              Hn : n = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * m = 0 *)&lt;br /&gt;
    rewrite Hn.            (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.           &lt;br /&gt;
  -                        (* n, m : nat&lt;br /&gt;
                              Hm : m = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * m = 0 *)&lt;br /&gt;
    rewrite Hm.            (* n * 0 = 0 *)&lt;br /&gt;
    rewrite &amp;lt;- mult_n_O.    (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Lemma disy_ej:&lt;br /&gt;
  forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m [Hn | Hm]. &lt;br /&gt;
  -                     (* n, m : nat&lt;br /&gt;
                           Hn : n = 0&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n * m = 0 *)&lt;br /&gt;
    rewrite Hn.         (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n, m : nat&lt;br /&gt;
                           Hm : m = 0&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n * m = 0 *)&lt;br /&gt;
    rewrite Hm.         (* n * 0 = 0 *)&lt;br /&gt;
    rewrite &amp;lt;- mult_n_O. (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. La táctica &amp;#039;destruct H as [Hn | Hm]&amp;#039;, cuando la hipótesis H es de&lt;br /&gt;
      la forma (A \/ B), la divide en dos casos: uno con hipótesis HA&lt;br /&gt;
      (afirmando la certeza de A) y otro con la hipótesis HB (afirmando&lt;br /&gt;
      la certeza de B).   &lt;br /&gt;
   2. La táctica &amp;#039;intros x [HA | HB]&amp;#039;, cuando el objetivo es de la&lt;br /&gt;
      forma (forall x, A \/ B -&amp;gt; C), intoduce la variable x y dos casos:&lt;br /&gt;
      uno con hipótesis HA (afirmando la certeza de A) y otro con la&lt;br /&gt;
      hipótesis HB (afirmando la certeza de B).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que&lt;br /&gt;
      forall A B : Prop, A -&amp;gt; A \/ B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma disy_intro: forall A B : Prop, A -&amp;gt; A \/ B.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B HA. (* A, B : Prop&lt;br /&gt;
                    HA : A&lt;br /&gt;
                    ============================&lt;br /&gt;
                    A \/ B *)&lt;br /&gt;
  left.          (* A *)&lt;br /&gt;
  apply HA.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;left&amp;#039; sustituye el objetivo de la forma (A \/ B)&lt;br /&gt;
   por A.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.3. Demostrar que&lt;br /&gt;
      forall n : nat, n = 0 \/ n = S (pred n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cero_o_sucesor:&lt;br /&gt;
  forall n : nat, n = 0 \/ n = S (pred n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    0 = 0 \/ 0 = S (Nat.pred 0) *)&lt;br /&gt;
    left.        (* 0 = 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* n : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    S n = 0 \/ S n = S (Nat.pred (S n)) *)&lt;br /&gt;
    right.       (* S n = S (Nat.pred (S n)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;right&amp;#039; sustituye el objetivo de la forma (A \/ B)&lt;br /&gt;
   por B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que&lt;br /&gt;
      forall n m, n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_eq_0 :&lt;br /&gt;
  forall n m, n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.          (* n, m : nat&lt;br /&gt;
                            H : n * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n = 0 \/ m = 0 *)&lt;br /&gt;
  destruct n as [|n&amp;#039;].&lt;br /&gt;
  -                      (* m : nat&lt;br /&gt;
                            H : 0 * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 = 0 \/ m = 0 *)&lt;br /&gt;
    left.                (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n&amp;#039;, m : nat&lt;br /&gt;
                            H : S n&amp;#039; * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ m = 0 *)&lt;br /&gt;
    destruct m as [|m&amp;#039;]. &lt;br /&gt;
    +                    (* n&amp;#039; : nat&lt;br /&gt;
                            H : S n&amp;#039; * 0 = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ 0 = 0 *)&lt;br /&gt;
      right.             (* 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                            H : S n&amp;#039; * S m&amp;#039; = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ S m&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.        (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                            H : S (m&amp;#039; + n&amp;#039; * S m&amp;#039;) = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ S m&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P \/ Q  -&amp;gt; Q \/ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem disy_conmutativa: forall P Q : Prop,&lt;br /&gt;
  P \/ Q  -&amp;gt; Q \/ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP | HQ]. &lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HP : P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q \/ P *)&lt;br /&gt;
    right.              (* P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HQ : Q&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q \/ P *)&lt;br /&gt;
    left.               (* Q *)&lt;br /&gt;
    apply HQ.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.4. Calcular el tipo de la expresión&lt;br /&gt;
      or&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check or.&lt;br /&gt;
(* ===&amp;gt; or : Prop -&amp;gt; Prop -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. (x \/ y) es una abreviatura de (or x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.3. Falsedad y negación  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module DefNot.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Definir la función&lt;br /&gt;
      not (P : Prop) : Prop&lt;br /&gt;
   tal que (not P) es la negación de P&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition not (P:Prop) : Prop :=&lt;br /&gt;
    P -&amp;gt; False.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Definir (~ x) como abreviatura de (not x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;~ x&amp;quot; := (not x) : type_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Esta es la forma como está definida la negación en Coq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End DefNot.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que&lt;br /&gt;
      forall (P:Prop),&lt;br /&gt;
        False -&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ex_falso_quodlibet: forall (P:Prop),&lt;br /&gt;
  False -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 P *)&lt;br /&gt;
  destruct H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. En latín, &amp;quot;ex falso quodlibet&amp;quot; significa &amp;quot;de lo falso (se&lt;br /&gt;
   sigue) cualquier cosa&amp;quot;. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.1. Demostrar que&lt;br /&gt;
      forall (P:Prop),&lt;br /&gt;
        ~ P -&amp;gt; (forall (Q:Prop), P -&amp;gt; Q).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact negacion_elim: forall (P:Prop),&lt;br /&gt;
  ~ P -&amp;gt; (forall (Q:Prop), P -&amp;gt; Q).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.     (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     forall P : Prop, (P -&amp;gt; False) -&amp;gt; forall Q : Prop, P -&amp;gt; Q *)&lt;br /&gt;
  intros P H1.    (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     ============================&lt;br /&gt;
                     forall Q : Prop, P -&amp;gt; Q *)&lt;br /&gt;
  intros Q H2.    (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     Q : Prop&lt;br /&gt;
                     H2 : P&lt;br /&gt;
                     ============================&lt;br /&gt;
                     Q *)&lt;br /&gt;
  apply H1 in H2. (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     Q : Prop&lt;br /&gt;
                     H2 : False&lt;br /&gt;
                     ============================&lt;br /&gt;
                     Q *)&lt;br /&gt;
  destruct H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que&lt;br /&gt;
      ~(0 = 1).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_no_es_uno: ~(0 = 1).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H.       (* H : 0 = 1&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La expresión (x &amp;lt;&amp;gt; y) es una abreviatura de ~(x = y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem cero_no_es_uno&amp;#039;: 0 &amp;lt;&amp;gt; 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H.       (* H : 0 = 1&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
  inversion H. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que&lt;br /&gt;
      ~ False&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem not_False :&lt;br /&gt;
  ~ False.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not. (* &lt;br /&gt;
                 ============================&lt;br /&gt;
                 False -&amp;gt; False *)&lt;br /&gt;
  intros H.   (* H : False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  destruct H. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        (P /\ ~P) -&amp;gt; Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem contradiccion_implica_cualquiera: forall P Q : Prop,&lt;br /&gt;
  (P /\ ~P) -&amp;gt; Q.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HNP]. (* P, Q : Prop&lt;br /&gt;
                          HP : P&lt;br /&gt;
                          HNP : ~ P&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  unfold not in HNP. (* P, Q : Prop&lt;br /&gt;
                          HP : P&lt;br /&gt;
                          HNP : P -&amp;gt; False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  apply HNP in HP. (* P, Q : Prop&lt;br /&gt;
                          HP : False&lt;br /&gt;
                          HNP : P -&amp;gt; False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  destruct HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.7. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        P -&amp;gt; ~~P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem doble_neg: forall P : Prop,&lt;br /&gt;
  P -&amp;gt; ~~P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 ~ ~ P *)&lt;br /&gt;
  unfold not. (* (P -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros G.   (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 G : P -&amp;gt; False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply G.    (* P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.2. Demostrar que&lt;br /&gt;
      forall (P Q : Prop),&lt;br /&gt;
        (P -&amp;gt; Q) -&amp;gt; (~Q -&amp;gt; ~P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem contrapositiva: forall (P Q : Prop),&lt;br /&gt;
  (P -&amp;gt; Q) -&amp;gt; (~Q -&amp;gt; ~P).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.          (* &lt;br /&gt;
                          ============================&lt;br /&gt;
                          forall P Q : Prop, &lt;br /&gt;
                            (P -&amp;gt; Q) -&amp;gt; (Q -&amp;gt; False) -&amp;gt; P -&amp;gt; False *)&lt;br /&gt;
  intros P Q H1 H2 H3. (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : P&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H1 in H3.      (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : Q&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H2 in H3.      (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.3. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        ~ (P /\ ~P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem no_contradiccion: forall P : Prop,&lt;br /&gt;
  ~ (P /\ ~P).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.       (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       forall P : Prop, P /\ (P -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros P [H1 H2]. (* P : Prop&lt;br /&gt;
                       H1 : P&lt;br /&gt;
                       H2 : P -&amp;gt; False&lt;br /&gt;
                       ============================&lt;br /&gt;
                       False *)&lt;br /&gt;
  apply H2.         (* P *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.8. Demostrar que&lt;br /&gt;
      forall b : bool,&lt;br /&gt;
        b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem no_verdadero_es_falso: forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] H.&lt;br /&gt;
  -                           (* H : true &amp;lt;&amp;gt; true&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = false *)&lt;br /&gt;
    unfold not in H.          (* H : true = true -&amp;gt; False&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = false *)&lt;br /&gt;
    apply ex_falso_quodlibet. (* H : true = true -&amp;gt; False&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 False *)&lt;br /&gt;
    apply H.                  (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* H : false &amp;lt;&amp;gt; true&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem no_verdadero_es_falso&amp;#039;: forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] H.&lt;br /&gt;
  -                  (* H : true &amp;lt;&amp;gt; true&lt;br /&gt;
                        ============================&lt;br /&gt;
                        true = false *)&lt;br /&gt;
    unfold not in H. (* H : true = true -&amp;gt; False&lt;br /&gt;
                        ============================&lt;br /&gt;
                        true = false *)&lt;br /&gt;
    exfalso.         (* H : true = true -&amp;gt; False&lt;br /&gt;
                        ============================&lt;br /&gt;
                        False *)&lt;br /&gt;
    apply H.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                  (* H : false &amp;lt;&amp;gt; true&lt;br /&gt;
                        ============================&lt;br /&gt;
                        false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas. &lt;br /&gt;
   1. Uso de &amp;#039;apply ex_falso_quodlibet&amp;#039; en la primera demostración.&lt;br /&gt;
   2. Uso de &amp;#039;exfalso&amp;#039; en la segunda demostración.&lt;br /&gt;
   3. La táctica &amp;#039;exfalso&amp;#039; sustituye el objetivo por falso. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.4. Verdad&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.1. Demostrar que la proposición True es verdadera.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma True_es_verdadera : True.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply I.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso del constructor I.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.5. Equivalencia lógica  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module DefIff.&lt;br /&gt;
&lt;br /&gt;
  (* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.1. Definir la función&lt;br /&gt;
      iff (P Q : Prop) : Prop&lt;br /&gt;
   tal que  (iff P Q) es la equivalencia de P y Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Definition iff (P Q : Prop) : Prop := (P -&amp;gt; Q) /\ (Q -&amp;gt; P).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.2. Definir (P &amp;lt;-&amp;gt; Q) como una abreviatura de (iff P Q). &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;P &amp;lt;-&amp;gt; Q&amp;quot; := (iff P Q)&lt;br /&gt;
                      (at level 95, no associativity)&lt;br /&gt;
                      : type_scope.&lt;br /&gt;
&lt;br /&gt;
End DefIff.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.3. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iff_sim : forall P Q : Prop,&lt;br /&gt;
  (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; P).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HPQ HQP]. (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q &amp;lt;-&amp;gt; P *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q -&amp;gt; P *)&lt;br /&gt;
    apply HQP.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; Q *)&lt;br /&gt;
    apply HPQ.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.4. Demostrar que&lt;br /&gt;
      forall b : bool,&lt;br /&gt;
        b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma not_true_iff_false : forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.                      (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                              (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true -&amp;gt; b = false *)&lt;br /&gt;
    apply no_verdadero_es_falso. &lt;br /&gt;
  -                              (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b = false -&amp;gt; b &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H.                    (* b : bool&lt;br /&gt;
                                    H : b = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true *)&lt;br /&gt;
    rewrite H.                   (* false &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H&amp;#039;.                   (* b : bool&lt;br /&gt;
                                    H : b = false&lt;br /&gt;
                                    H&amp;#039; : false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    False *)&lt;br /&gt;
    inversion H&amp;#039;.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.4. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        P &amp;lt;-&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma iff_refl_aux: forall P : Prop,&lt;br /&gt;
    P -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem iff_refl: forall P : Prop,&lt;br /&gt;
    P &amp;lt;-&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                     (* P : Prop&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; P *)&lt;br /&gt;
    apply iff_refl_aux. &lt;br /&gt;
  -                     (* P : Prop&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; P *)&lt;br /&gt;
    apply iff_refl_aux.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.5. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; R) -&amp;gt; (P &amp;lt;-&amp;gt; R).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iff_trans: forall P Q R : Prop,&lt;br /&gt;
  (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; R) -&amp;gt; (P &amp;lt;-&amp;gt; R).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R [HPQ HQP] [HQR HRQ]. (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P &amp;lt;-&amp;gt; R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                                 (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P -&amp;gt; R *)&lt;br /&gt;
    intros HP.                      (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       HP : P&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       R *)&lt;br /&gt;
    apply HQR.                      (* Q *)&lt;br /&gt;
    apply HPQ.                      (* P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
  -                                 (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       R -&amp;gt; P *)&lt;br /&gt;
    intros HR.                      (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       HR : R&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P *)&lt;br /&gt;
    apply HQP.                      (* Q *)&lt;br /&gt;
    apply HRQ.                      (* R *)&lt;br /&gt;
    apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.6. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        P \/ (Q /\ R) &amp;lt;-&amp;gt; (P \/ Q) /\ (P \/ R).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem distributiva_disy_conj: forall P Q R : Prop,&lt;br /&gt;
  P \/ (Q /\ R) &amp;lt;-&amp;gt; (P \/ Q) /\ (P \/ R).&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                             (* P, Q, R : Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) -&amp;gt; (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
    intros [HP | [HQ HR]].&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ Q *)&lt;br /&gt;
        left.                   (* P *)&lt;br /&gt;
        apply HP.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ R *)&lt;br /&gt;
        left.                   (* P *)&lt;br /&gt;
        apply HP.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ Q *)&lt;br /&gt;
        right.                  (* Q *)&lt;br /&gt;
        apply HQ.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ R *)&lt;br /&gt;
        right.                  (* R *)&lt;br /&gt;
        apply HR.&lt;br /&gt;
  -                             (* P, Q, R : Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) -&amp;gt; P \/ (Q /\ R) *)&lt;br /&gt;
    intros [[HP1|HQ] [HP2|HR]]. &lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP1, HP2 : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP1.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP1 : P&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP1.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HP2 : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP2.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      right.                    (* Q /\ R *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Q *)&lt;br /&gt;
        apply HQ.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   R *)&lt;br /&gt;
        apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Se importa la librería Coq.Setoids.Setoid para usar las&lt;br /&gt;
   tácticas reflexivity y rewrite con iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Require Import Coq.Setoids.Setoid.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.5. Demostrar que&lt;br /&gt;
      forall n m : nat, n * m = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_0 : forall n m : nat, n * m = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                  (* n, m : nat&lt;br /&gt;
                        ============================&lt;br /&gt;
                        n * m = 0 -&amp;gt; n = 0 \/ m = 0 *)&lt;br /&gt;
    apply mult_eq_0. &lt;br /&gt;
  -                  (* n, m : nat&lt;br /&gt;
                        ============================&lt;br /&gt;
                        n = 0 \/ m = 0 -&amp;gt; n * m = 0 *)&lt;br /&gt;
    apply disy_ej.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.6. Demostrar que&lt;br /&gt;
      forall P Q R : Prop, &lt;br /&gt;
        P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma disy_asociativa :&lt;br /&gt;
  forall P Q R : Prop, P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R.           (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                       (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) -&amp;gt; (P \/ Q) \/ R *)&lt;br /&gt;
    intros [H | [H | H]]. &lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P \/ Q *)&lt;br /&gt;
      left.               (* P *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : Q&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P \/ Q *)&lt;br /&gt;
      right.              (* Q *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : R&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      right.              (* R *)&lt;br /&gt;
      apply H.&lt;br /&gt;
  -                       (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R -&amp;gt; P \/ (Q \/ R) *)&lt;br /&gt;
    intros [[H | H] | H].&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : Q&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) *)&lt;br /&gt;
      right.              (* Q \/ R *)&lt;br /&gt;
      left.               (* Q *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : R&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) *)&lt;br /&gt;
      right.              (* Q \/ R *)&lt;br /&gt;
      right.              (* R *)&lt;br /&gt;
      apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.7. Demostrar que&lt;br /&gt;
      forall n m p : nat,&lt;br /&gt;
        n * m * p = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0 \/ p = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_0_3: forall n m p : nat,&lt;br /&gt;
    n * m * p = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0 \/ p = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.            (* n, m, p : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * (m * p) = 0 &amp;lt;-&amp;gt; n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite mult_0.          (* n * m = 0 \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite mult_0.          (* (n = 0 \/ m = 0) \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite disy_asociativa. (* (n = 0 \/ m = 0) \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              (n = 0 \/ m = 0) \/ p = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de reflexivity y rewrite con iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.8. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_apply_iff: forall n m : nat,&lt;br /&gt;
    n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : n * m = 0&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = 0 \/ m = 0 *)&lt;br /&gt;
  apply mult_0. (* n * m = 0 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de apply sobre iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.6. Cuantificación existencial  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.1. Demostrar que&lt;br /&gt;
      exists n : nat, 4 = n + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuatro_es_par: exists n : nat, 4 = n + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  exists 2.          (* &lt;br /&gt;
                   ============================&lt;br /&gt;
                   4 = 2 + 2 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;exists a&amp;#039; sustituye el objetivo de la forma &lt;br /&gt;
   (exists x, P(x)) por P(a).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(** Conversely, if we have an existential hypothesis [exists x, P] in&lt;br /&gt;
    the context, we can destruct it to obtain a witness [x] and a&lt;br /&gt;
    hypothesis stating that [P] holds of [x]. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.2. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        (exists m, n = 4 + m) -&amp;gt; (exists o, n = 2 + o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem ej_existe_2a: forall n : nat,&lt;br /&gt;
  (exists m, n = 4 + m) -&amp;gt;&lt;br /&gt;
  (exists o, n = 2 + o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.&lt;br /&gt;
  destruct H as [a Ha].&lt;br /&gt;
  exists (2 + a).&lt;br /&gt;
  apply Ha.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem ej_existe_2b: forall n : nat,&lt;br /&gt;
  (exists m, n = 4 + m) -&amp;gt;&lt;br /&gt;
  (exists o, n = 2 + o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n [a Ha]. &lt;br /&gt;
  exists (2 + a).&lt;br /&gt;
  apply Ha.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. &amp;#039;destruct H [a Ha]&amp;#039; sustituye la hipótesis (H : exists x, P(x)) &lt;br /&gt;
      por (Ha : P(a)).&lt;br /&gt;
   2. &amp;#039;intros x [a Ha]&amp;#039; sustituye el objetivo &lt;br /&gt;
      (forall x, (exists y P(y)) -&amp;gt; Q(x)) por Q(x) y le añade la&lt;br /&gt;
      hipótesis (Ha : P(a)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.1. Demostrar que&lt;br /&gt;
      forall (X:Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
        (forall x, P x) -&amp;gt; ~ (exists x, ~ P x)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem paraTodo_no_existe_no: forall (X:Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
  (forall x, P x) -&amp;gt; ~ (exists x, ~ P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X P H1 [a Ha]. (* X : Type&lt;br /&gt;
                           P : X -&amp;gt; Prop&lt;br /&gt;
                           H1 : forall x : X, P x&lt;br /&gt;
                           a : X&lt;br /&gt;
                           Ha : ~ P a&lt;br /&gt;
                           ============================&lt;br /&gt;
                           False *)&lt;br /&gt;
  apply Ha.             (* P a *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (P Q : X -&amp;gt; Prop),&lt;br /&gt;
        (exists x, P x \/ Q x) &amp;lt;-&amp;gt; (exists x, P x) \/ (exists x, Q x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem dist_existe: forall (X : Type) (P Q : X -&amp;gt; Prop),&lt;br /&gt;
  (exists x, P x \/ Q x) &amp;lt;-&amp;gt; (exists x, P x) \/ (exists x, Q x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X P Q.                 (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x \/ Q x) &amp;lt;-&amp;gt; &lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x : X, P x \/ Q x) -&amp;gt; &lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
    intros [a [HPa | HQa]].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HPa : P a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
      left.                     (* exists x : X, P x *)&lt;br /&gt;
      exists a.                      (* P a *)&lt;br /&gt;
      apply HPa.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HQa : Q a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
      right.                    (* exists x : X, Q x *)&lt;br /&gt;
      exists a.                      (* Q a *)&lt;br /&gt;
      apply HQa.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) -&amp;gt; &lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
    intros [[a HPa] | [a HQa]]. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HPa : P a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
      exists a.                      (* P a \/ Q a *)&lt;br /&gt;
      left.                     (* P a *)&lt;br /&gt;
      apply HPa.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HQa : Q a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
      exists a.                      (* P a \/ Q a *)&lt;br /&gt;
      right.                    (* Q a *)&lt;br /&gt;
      apply HQa.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programación con proposiciones  == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.1. Definir la función&lt;br /&gt;
      En {A : Type} (x : A) (xs : list A) : Prop :=&lt;br /&gt;
   tal que (En x xs) se verifica si x pertenece a xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint En {A : Type} (x : A) (xs : list A) : Prop :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []        =&amp;gt; False&lt;br /&gt;
  | x&amp;#039; :: xs&amp;#039; =&amp;gt; x&amp;#039; = x \/ En x xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.2. Demostrar que&lt;br /&gt;
      En 4 [1; 2; 3; 4; 5].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example En_ejemplo_1 : En 4 [1; 2; 3; 4; 5].&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* 1 = 4 \/ 2 = 4 \/ 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 2 = 4 \/ 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  left.        (* 4 = 4 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.3. Demostrar que&lt;br /&gt;
      forall n : nat, &lt;br /&gt;
        En n [2; 4] -&amp;gt; exists n&amp;#039;, n = 2 * n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example En_ejemplo_2: forall n : nat,&lt;br /&gt;
    En n [2; 4] -&amp;gt; exists n&amp;#039;, n = 2 * n&amp;#039;.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.                   (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              forall n : nat,&lt;br /&gt;
                               2 = n \/ 4 = n \/ False -&amp;gt; &lt;br /&gt;
                               exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
  intros n [H | [H | []]]. &lt;br /&gt;
  -                        (* n : nat&lt;br /&gt;
                              H : 2 = n&lt;br /&gt;
                              ============================&lt;br /&gt;
                              exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
    exists 1.                   (* n = 1 + (1 + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- H.           (* 2 = 1 + (1 + 0) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* n : nat&lt;br /&gt;
                              H : 4 = n&lt;br /&gt;
                              ============================&lt;br /&gt;
                              exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
    exists 2.                   (* n = 2 + (2 + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- H.           (* 4 = 2 + (2 + 0) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso del patrón vacóp para descartar el último caso.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (x : A),&lt;br /&gt;
        En x xs -&amp;gt;&lt;br /&gt;
        En (f x) (map f xs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lemma En_map: forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (x : A),&lt;br /&gt;
    En x xs -&amp;gt;&lt;br /&gt;
    En (f x) (map f xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f xs x.            (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   xs : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x xs -&amp;gt; En (f x) (map f xs) *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x [ ] -&amp;gt; En (f x) (map f [ ]) *)&lt;br /&gt;
    simpl.                      (* False -&amp;gt; False *)&lt;br /&gt;
    intros [].&lt;br /&gt;
  -                             (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x (x&amp;#039;::xs&amp;#039;) -&amp;gt; &lt;br /&gt;
                                   En (f x) (map f (x&amp;#039;::xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                      (* x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
    intros [H | H].&lt;br /&gt;
    +                           (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   H : x&amp;#039; = x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      rewrite H.                (* f x = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      left.                     (* f x = f x *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   H : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      right.                    (* En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      apply HI.                 (* En x xs&amp;#039; *)&lt;br /&gt;
      apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (y : B),&lt;br /&gt;
        En y (map f xs) &amp;lt;-&amp;gt;&lt;br /&gt;
        exists x, f x = y /\ En x xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma En_map_iff: forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (y : B),&lt;br /&gt;
    En y (map f xs) &amp;lt;-&amp;gt;&lt;br /&gt;
    exists x, f x = y /\ En x xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f xs y.                  (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         xs : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f xs) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x xs) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                                   (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f [ ]) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x [ ]) *)&lt;br /&gt;
    simpl.                            (* En y (map f [ ]) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x [ ]) *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         False -&amp;gt; &lt;br /&gt;
                                         exists x : A, f x = y /\ False *)&lt;br /&gt;
      intros [].&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         (exists x : A, f x = y /\ False) -&amp;gt; &lt;br /&gt;
                                         False *)&lt;br /&gt;
      intros [a [H []]].&lt;br /&gt;
  -                                   (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f (x :: xs&amp;#039;)) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                           f x0 = y /\ En x0 (x :: xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                            (* f x = y \/ En y (map f xs&amp;#039;) &amp;lt;-&amp;gt;&lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                           f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;)) *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) -&amp;gt;&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
      intros [H1 | H2].&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        exists x.                        (* f x = y /\ (x = x \/ En x xs&amp;#039;) *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y *)&lt;br /&gt;
          apply H1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         x = x \/ En x xs&amp;#039; *)&lt;br /&gt;
          left.                       (* x = x *)&lt;br /&gt;
          reflexivity.&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H2 : En y (map f xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        apply HI in H2.               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H2 : exists x : A, f x = y /\ En x xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        destruct H2 as [a [Ha1 Ha2]]. (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        &lt;br /&gt;
        exists a.                          (* En y (map f xs) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x xs) *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f a = y *)&lt;br /&gt;
          apply Ha1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         x = a \/ En a xs&amp;#039; *)&lt;br /&gt;
          right.                      (* En a xs&amp;#039; *)&lt;br /&gt;
          apply Ha2.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x : A, &lt;br /&gt;
                                                f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;)) -&amp;gt;&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
      intros [a [Ha1 [Ha2 | Ha3]]].&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : x = a&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
        left.                         (* f x = y *)&lt;br /&gt;
        rewrite Ha2.                  (* f a = y *)&lt;br /&gt;
        rewrite Ha1.                  (* y = y *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
        right.                        (* En y (map f xs&amp;#039;) *)&lt;br /&gt;
        apply HI.                     (* exists x0 : A, f x0 = y /\ En x0 xs&amp;#039; *)&lt;br /&gt;
        exists a.                          (* f a = y /\ En a xs&amp;#039; *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f a = y *)&lt;br /&gt;
          apply Ha1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En a xs&amp;#039; *)&lt;br /&gt;
          apply Ha3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall A (xs ys : list A) (a : A),&lt;br /&gt;
        En a (xs ++ ys) &amp;lt;-&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma En_conc_1: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a (xs ++ ys) -&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].    &lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a ([ ] ++ ys) -&amp;gt; En a [ ] \/ En a ys *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a ys -&amp;gt; False \/ En a ys *)&lt;br /&gt;
    intros ys a H.                (* A : Type&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     False \/ En a ys *)&lt;br /&gt;
    right.                        (* En a ys *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A),&lt;br /&gt;
                                      En a ((x :: xs&amp;#039;) ++ ys) -&amp;gt; &lt;br /&gt;
                                      En a (x :: xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A),&lt;br /&gt;
                                      x = a \/ En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                      (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
    intros ys a [H1 | H2].&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H1 : x = a&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
      left.                       (* x = a \/ En a xs&amp;#039; *)&lt;br /&gt;
      left.                       (* x = a *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H2 : En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
      rewrite &amp;lt;- disy_asociativa.  (* x = a \/ (En a xs&amp;#039; \/ En a ys) *)&lt;br /&gt;
      right.                      (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      apply HI.                   (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma En_conc_2: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a xs \/ En a ys -&amp;gt; En a (xs ++ ys). &lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a [ ] \/ En a ys -&amp;gt; En a ([ ] ++ ys) *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A), &lt;br /&gt;
                                      False \/ En a ys -&amp;gt; En a ys *)&lt;br /&gt;
    intros ys a [[] | H].         (* A : Type&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a ys *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A),&lt;br /&gt;
                                      En a (x :: xs&amp;#039;) \/ En a ys -&amp;gt; &lt;br /&gt;
                                      En a ((x :: xs&amp;#039;) ++ ys) *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A),&lt;br /&gt;
                                      (x = a \/ En a xs&amp;#039;) \/ En a ys -&amp;gt; &lt;br /&gt;
                                      x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
    intros ys a [[H1 | H2] | H3]. &lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H1 : x = a&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      left.                       (* x = a *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H2 : En a xs&amp;#039;&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      right.                      (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply HI.                   (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      left.                       (* En a xs&amp;#039; *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H3 : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      right.                      (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply HI.                   (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      right.                      (* En a ys *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
Lemma En_conc: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a (xs ++ ys) &amp;lt;-&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                  (* A : Type&lt;br /&gt;
                        xs, ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a (xs ++ ys) -&amp;gt; En a xs \/ En a ys *)&lt;br /&gt;
    apply En_conc_1. &lt;br /&gt;
  -                  (* A : Type&lt;br /&gt;
                                     xs, ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a xs \/ En a ys -&amp;gt; En a (xs ++ ys) *)&lt;br /&gt;
    apply En_conc_2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3.1. Definir la propiedad&lt;br /&gt;
      Todos {T : Type} (P : T -&amp;gt; Prop) (xs : list T) : Prop&lt;br /&gt;
   tal que (Todos P xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   la propiedad P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint Todos {T : Type} (P : T -&amp;gt; Prop) (xs : list T) : Prop :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; True&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; P x /\ Todos P xs&amp;#039; &lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3.2. Demostrar que&lt;br /&gt;
      forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
        (forall x, En x xs -&amp;gt; P x) &amp;lt;-&amp;gt;&lt;br /&gt;
        Todos P xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En_1: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x) -&amp;gt;&lt;br /&gt;
    Todos P xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].  &lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (forall x : T, En x [ ] -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                   Todos P [ ] *) &lt;br /&gt;
    simpl.                      (* (forall x : T, False -&amp;gt; P x) -&amp;gt; True *)&lt;br /&gt;
    intros.                     (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   H : forall x : T, False -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   True *)&lt;br /&gt;
    apply I.&lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (forall x : T, En x (x&amp;#039; :: xs&amp;#039;) -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                   Todos P (x&amp;#039; :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* (forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x) -&amp;gt;&lt;br /&gt;
                                   P x&amp;#039; /\ Todos P xs&amp;#039; *)&lt;br /&gt;
    intros H.                   (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x&amp;#039; /\ Todos P xs&amp;#039; *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x&amp;#039; *)&lt;br /&gt;
      apply H.                  (* x&amp;#039; = x&amp;#039; \/ En x&amp;#039; xs&amp;#039; *)&lt;br /&gt;
      left.                     (* x&amp;#039; = x&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P xs&amp;#039; *)&lt;br /&gt;
      apply HI.                 (* forall x : T, En x xs&amp;#039; -&amp;gt; P x *)&lt;br /&gt;
      intros x H1.              (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H1 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      apply H.                  (* x&amp;#039; = x \/ En x xs&amp;#039; *)&lt;br /&gt;
      right.                    (* En x xs&amp;#039; *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En_2: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    Todos P xs -&amp;gt;&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P [ ] -&amp;gt; &lt;br /&gt;
                                   forall x : T, En x [ ] -&amp;gt; P x *)&lt;br /&gt;
    simpl.                      (* True -&amp;gt; forall x : T, False -&amp;gt; P x *)&lt;br /&gt;
    intros [].                  (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall x : T, False -&amp;gt; P x *)&lt;br /&gt;
    intros x [].&lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P (x&amp;#039; :: xs&amp;#039;) -&amp;gt; &lt;br /&gt;
                                   forall x : T, En x (x&amp;#039; :: xs&amp;#039;) -&amp;gt; P x *)&lt;br /&gt;
    simpl.                      (* P x&amp;#039; /\ Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                   forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x *)&lt;br /&gt;
    intros [H1 H2] x [H3 | H4]. &lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H3 : x&amp;#039; = x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      rewrite &amp;lt;- H3.             (* P x&amp;#039; *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
      *                         (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P xs&amp;#039; *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
      *                         (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x xs&amp;#039; *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x) &amp;lt;-&amp;gt;&lt;br /&gt;
    Todos P xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                   (* T : Type&lt;br /&gt;
                         P : T -&amp;gt; Prop&lt;br /&gt;
                         xs : list T&lt;br /&gt;
                         ============================&lt;br /&gt;
                         (forall x : T, En x xs -&amp;gt; P x) -&amp;gt; Todos P xs *)&lt;br /&gt;
    apply Todos_En_1. &lt;br /&gt;
  -                   (* T : Type&lt;br /&gt;
                         P : T -&amp;gt; Prop&lt;br /&gt;
                         xs : list T&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Todos P xs -&amp;gt; forall x : T, En x xs -&amp;gt; P x *)&lt;br /&gt;
    apply Todos_En_2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.1. Definir la propiedad&lt;br /&gt;
      combina_par_impar (Pimpar Ppar : nat -&amp;gt; Prop) : nat -&amp;gt; Prop&lt;br /&gt;
   tal que (combina_par_impar Pimpar Ppar) es una función que asigna a n&lt;br /&gt;
   (Pimpar n) si n es impar y (Ppar n) si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition combina_par_impar (Pimpar Ppar : nat -&amp;gt; Prop) : nat -&amp;gt; Prop :=&lt;br /&gt;
  fun n =&amp;gt; (esImpar n = true -&amp;gt; Pimpar n) /\&lt;br /&gt;
        (esImpar n = false -&amp;gt; Ppar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.2. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        (esImpar n = true -&amp;gt; Pimpar n) -&amp;gt;&lt;br /&gt;
        (esImpar n = false -&amp;gt; Ppar n) -&amp;gt;&lt;br /&gt;
        combina_par_impar Pimpar Ppar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_intro :&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    (esImpar n = true -&amp;gt; Pimpar n) -&amp;gt;&lt;br /&gt;
    (esImpar n = false -&amp;gt; Ppar n) -&amp;gt;&lt;br /&gt;
    combina_par_impar Pimpar Ppar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Par n H1 H2. (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                combina_par_impar Pimpar Par n *)&lt;br /&gt;
  unfold combina_par_impar.  (* (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                (esImpar n = false -&amp;gt; Par n) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                          (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                esImpar n = true -&amp;gt; Pimpar n *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                esImpar n = false -&amp;gt; Par n *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.3. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
        esImpar n = true -&amp;gt;&lt;br /&gt;
        Pimpar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_elim_impar:&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
    esImpar n = true -&amp;gt;&lt;br /&gt;
    Pimpar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Ppar n H1 H2.     (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : combina_par_impar Pimpar Ppar n&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                    Pimpar n *)&lt;br /&gt;
  unfold combina_par_impar in H1. (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                          (esImpar n = false -&amp;gt; Ppar n)&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Pimpar n *)&lt;br /&gt;
  destruct H1 as [H3 H4].         (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H3 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                     H4 : esImpar n = false -&amp;gt; Ppar n&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Pimpar n *)&lt;br /&gt;
  apply H3.                       (* esImpar n = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.4. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
        esImpar n = false -&amp;gt;&lt;br /&gt;
        Ppar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_elim_par:&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
    esImpar n = false -&amp;gt;&lt;br /&gt;
    Ppar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Ppar n H1 H2.     (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : combina_par_impar Pimpar Ppar n&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  unfold combina_par_impar in H1. (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                          (esImpar n = false -&amp;gt; Ppar n)&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  destruct H1 as [H3 H4].         (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H3 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                     H4 : esImpar n = false -&amp;gt; Ppar n&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  apply H4.                       (* esImpar n = false *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Aplicando teoremas a argumentos == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Evaluar la expresión&lt;br /&gt;
      Check suma_conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check suma_conmutativa.&lt;br /&gt;
(* ===&amp;gt; forall n m : nat, n + m = m + n *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En Coq, las demostraciones son objetos de primera clase.&lt;br /&gt;
   2. Coq devuelve el tipo de suma_conmutativa como es de cualquier&lt;br /&gt;
      expresión.&lt;br /&gt;
   3. El identificador suma_conmutativa representa un objeto prueba de&lt;br /&gt;
      (forall n m : nat, n + m = m + n).&lt;br /&gt;
   4. Un término de tipo (nat -&amp;gt; nat -&amp;gt; nat) transforma dos naturales en&lt;br /&gt;
      un natural.&lt;br /&gt;
   5. Análogamente, un término de tipo (n = m -&amp;gt; n + n = m + m)&lt;br /&gt;
      transforma un argumento de tipo (n = m) en otro de tipo &lt;br /&gt;
      (n + n = m + m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Operationally, this analogy goes even further: by applying a&lt;br /&gt;
    theorem, as if it were a function, to hypotheses with matching&lt;br /&gt;
    types, we can specialize its result without having to resort to&lt;br /&gt;
    intermediate assertions.  For example, suppose we wanted to prove&lt;br /&gt;
    the following result: *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.2. Demostrar que&lt;br /&gt;
      forall x y z : nat, &lt;br /&gt;
        x + (y + z) = (z + y) + x.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Lemma suma_conmutativa3a :&lt;br /&gt;
  forall x y z : nat,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.             (* x, y, z : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               x + (y + z) = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa. (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa. (* x + (y + z) = (z + y) + x *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Lemma suma_conmutativa3b :&lt;br /&gt;
  forall x y z,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.               (* x, y, z : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x + (y + z) = z + y + x *)&lt;br /&gt;
  rewrite suma_conmutativa.   (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  assert (H : y + z = z + y). &lt;br /&gt;
  -                           (* x, y, z : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 y + z = z + y *)&lt;br /&gt;
    rewrite suma_conmutativa. (* z + y = z + y *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* x, y, z : nat&lt;br /&gt;
                                 H : y + z = z + y&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (y + z) + x = (z + y) + x *)&lt;br /&gt;
    rewrite H.                (* (z + y) + x = (z + y) + x *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 3º intento *)&lt;br /&gt;
Lemma suma_conmutativa3c:&lt;br /&gt;
  forall x y z,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.                   (* x, y, z : nat&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x + (y + z) = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa.       (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  rewrite (suma_conmutativa y z). (* (z + y) + x = (z + y) + x *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Indicación en (rewrite (suma_conmutativa y z)) de los&lt;br /&gt;
   argumentos con los que se aplica, análogamente a las funciones&lt;br /&gt;
   polimórficas. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.3. Demostrar que&lt;br /&gt;
     forall {n : nat} {ns : list nat},&lt;br /&gt;
       En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
       n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Lema auxiliar *)&lt;br /&gt;
Lemma producto_n_0:&lt;br /&gt;
  forall n : nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              0 * 0 = 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                        (* n&amp;#039; : nat&lt;br /&gt;
                              HI : n&amp;#039; * 0 = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              S n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    simpl.                 (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ej_aplicacion_de_lema_1:&lt;br /&gt;
  forall {n : nat} {ns : list nat},&lt;br /&gt;
    En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
    n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n ns H.              (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  rewrite En_map_iff in H.    (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 H : exists x : nat, x * 0 = n /\ En x ns&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  destruct H as [m [Hm _]].   (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 m : nat&lt;br /&gt;
                                 Hm : m * 0 = n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  rewrite producto_n_0 in Hm. (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 m : nat&lt;br /&gt;
                                 Hm : 0 = n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  symmetry.                   (* 0 = n *)&lt;br /&gt;
  apply Hm.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ej_aplicacion_de_lema:&lt;br /&gt;
  forall {n : nat} {ns : list nat},&lt;br /&gt;
    En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
    n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n ns H.                    (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  destruct (conj_e1 _ _&lt;br /&gt;
             (En_map_iff _ _ _ _ _) &lt;br /&gt;
             H)&lt;br /&gt;
           as [m [Hm _]].           (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       m : nat&lt;br /&gt;
                                       Hm : m * 0 = n&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  rewrite producto_n_0 in Hm.       (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       m : nat&lt;br /&gt;
                                       Hm : 0 = n&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  symmetry.                         (* 0 = n *)&lt;br /&gt;
  apply Hm.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Aplicación de teoremas a argumentos con&lt;br /&gt;
      (conj_e1 _ _  (En_map_iff _ _ _ _ _) H)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Coq vs. teoría de conjuntos == &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En lugar de decir que un elemento pertenece a un conjunto se puede&lt;br /&gt;
      decir que verifica la propiedad que define al conjunto.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.1. Extensionalidad funcional&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.1. Demostrar que&lt;br /&gt;
      plus 3 = plus (pred 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example igualdad_de_funciones_ej1:&lt;br /&gt;
  suma 3 = suma (pred 4).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.2. Definir el axioma de extensionalidad funcional que&lt;br /&gt;
   afirma que dos funciones son giuales cuando tienen los mismos&lt;br /&gt;
   valores. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Axiom extensionalidad_funcional : forall {X Y: Type}&lt;br /&gt;
                                    {f g : X -&amp;gt; Y},&lt;br /&gt;
  (forall (x:X), f x = g x) -&amp;gt; f = g.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.3. Demostrar que&lt;br /&gt;
      (fun x =&amp;gt; suma x 1) = (fun x =&amp;gt; suma 1 x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example igualdad_de_funciones_ej2 :&lt;br /&gt;
  (fun x =&amp;gt; suma x 1) = (fun x =&amp;gt; suma 1 x).&lt;br /&gt;
Proof.&lt;br /&gt;
  apply extensionalidad_funcional. (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      forall x : nat, suma x 1 = suma 1 x *)&lt;br /&gt;
  intros x.                        (* x : nat&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      suma x 1 = suma 1 x *)&lt;br /&gt;
  apply suma_conmutativa.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. No se puede demostrar sin el axioma.&lt;br /&gt;
   2. Hay que ser cuidadoso en la definición de axiomas, porque se&lt;br /&gt;
      pueden introducir inconsistencias. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.4. Calcular los axiomas usados en la prueba de &lt;br /&gt;
      igualdad_de_funciones_ej2&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Print Assumptions igualdad_de_funciones_ej2.&lt;br /&gt;
(* ===&amp;gt;&lt;br /&gt;
     Axioms:&lt;br /&gt;
     extensionalidad_funcional :&lt;br /&gt;
         forall (X Y : Type) (f g : X -&amp;gt; Y),&lt;br /&gt;
                (forall x : X, f x = g x) -&amp;gt; f = g *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1.1. Se considera la siguiente definición iterativa de la&lt;br /&gt;
   función inversa&lt;br /&gt;
      Fixpoint inversaIaux {X} (xs ys : list X) : list X :=&lt;br /&gt;
        match xs with&lt;br /&gt;
        | []       =&amp;gt; ys&lt;br /&gt;
        | x :: xs&amp;#039; =&amp;gt; inversaIaux xs&amp;#039; (x :: ys)&lt;br /&gt;
        end.&lt;br /&gt;
      &lt;br /&gt;
      Definition inversaI {X} (xs : list X) : list X :=&lt;br /&gt;
        inversaIaux xs [].&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall X : Type, &lt;br /&gt;
        @inversaI X = @inversa X.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint inversaIaux {X} (xs ys : list X) : list X :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []       =&amp;gt; ys&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; inversaIaux xs&amp;#039; (x :: ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Definition inversaI {X} (xs : list X) : list X :=&lt;br /&gt;
  inversaIaux xs [].&lt;br /&gt;
&lt;br /&gt;
Lemma inversaI_correcta_aux:&lt;br /&gt;
  forall (X : Type) (xs ys : list X),&lt;br /&gt;
    inversaIaux xs ys = inversa xs ++ ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux xs ys = inversa xs ++ ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].  &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux [ ] ys = inversa [ ] ++ ys *)&lt;br /&gt;
    simpl.                      (* forall ys : list X, ys = ys *)&lt;br /&gt;
    intros.                     (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   ys = ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : forall ys : list X, &lt;br /&gt;
                                         inversaIaux xs&amp;#039; ys = inversa xs&amp;#039; ++ ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux (x :: xs&amp;#039;) ys = &lt;br /&gt;
                                    inversa (x :: xs&amp;#039;) ++ ys *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : forall ys : list X, &lt;br /&gt;
                                         inversaIaux xs&amp;#039; ys = inversa xs&amp;#039; ++ ys&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   inversaIaux (x :: xs&amp;#039;) ys = &lt;br /&gt;
                                   inversa (x :: xs&amp;#039;) ++ ys *)&lt;br /&gt;
    simpl.                      (* inversaIaux xs&amp;#039; (x :: ys) = &lt;br /&gt;
                                   (inversa xs&amp;#039; ++ [x]) ++ ys *)&lt;br /&gt;
    rewrite &amp;lt;- conc_asociativa.  (* inversaIaux xs&amp;#039; (x :: ys) = &lt;br /&gt;
                                   inversa xs&amp;#039; ++ ([x] ++ ys) *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
                                            &lt;br /&gt;
Lemma inversaI_correcta:&lt;br /&gt;
  forall X : Type,&lt;br /&gt;
    @inversaI X = @inversa X.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X.                        (* X : Type&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      inversaI = inversa *)&lt;br /&gt;
  apply extensionalidad_funcional. (* forall x : list X, &lt;br /&gt;
                                       inversaI x = inversa x *)&lt;br /&gt;
  intros.                          (* X : Type&lt;br /&gt;
                                      x : list X&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      inversaI x = inversa x *)&lt;br /&gt;
  unfold inversaI.                 (* inversaIaux x [ ] = inversa x *)&lt;br /&gt;
  rewrite inversaI_correcta_aux.   (* inversa x ++ [ ] = inversa x *)&lt;br /&gt;
  apply conc_nil.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.2. Proposiciones y booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.1. Demostrar que&lt;br /&gt;
     forall k : nat,&lt;br /&gt;
       esPar (doble k) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_doble:&lt;br /&gt;
  forall k : nat,&lt;br /&gt;
    esPar (doble k) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros k.                (* k : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble k) = true *)&lt;br /&gt;
  induction k as [|k&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble 0) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* k&amp;#039; : nat&lt;br /&gt;
                              HI : esPar (doble k&amp;#039;) = true&lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble (S k&amp;#039;)) = true *)&lt;br /&gt;
    simpl.                 (* esPar (doble k&amp;#039;) = true *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.1. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        exists k : nat, n = if esPar n&lt;br /&gt;
                     then doble k&lt;br /&gt;
                     else S (doble k).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_doble_aux :&lt;br /&gt;
  forall n : nat,&lt;br /&gt;
    exists k : nat, n = if esPar n&lt;br /&gt;
                 then doble k&lt;br /&gt;
                 else S (doble k).&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HI].    &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   0 = (if esPar 0 &lt;br /&gt;
                                        then doble k &lt;br /&gt;
                                        else S (doble k)) *)&lt;br /&gt;
    exists 0.                       (* 0 = (if esPar 0 &lt;br /&gt;
                                       then doble 0 &lt;br /&gt;
                                       else S (doble 0)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* n&amp;#039; : nat&lt;br /&gt;
                                  HI : exists k : nat, &lt;br /&gt;
                                        n&amp;#039; = (if esPar n&amp;#039; &lt;br /&gt;
                                              then doble k &lt;br /&gt;
                                              else S (doble k))&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
    destruct (esPar n&amp;#039;) eqn:H. &lt;br /&gt;
    +                          (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = true&lt;br /&gt;
                                  HI : exists k : nat, n&amp;#039; = doble k&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite esPar_S.         (* exists k : nat,&lt;br /&gt;
                                   S n&amp;#039; = (if negacion (esPar n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite H.               (* exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if negacion true &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      simpl.                   (* exists k : nat, S n&amp;#039; = S (doble k) *)&lt;br /&gt;
      destruct HI as [k&amp;#039; Hk&amp;#039;]. (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = true&lt;br /&gt;
                                  k&amp;#039; : nat&lt;br /&gt;
                                  Hk&amp;#039; : n&amp;#039; = doble k&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, S n&amp;#039; = S (doble k) *)&lt;br /&gt;
      exists k&amp;#039;.                    (* S n&amp;#039; = S (doble k&amp;#039;) *)&lt;br /&gt;
      rewrite Hk&amp;#039;.             (* S (doble k&amp;#039;) = S (doble k&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = false&lt;br /&gt;
                                  HI : exists k : nat, n&amp;#039; = S (doble k)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite esPar_S.         (* exists k : nat,&lt;br /&gt;
                                   S n&amp;#039; = (if negacion (esPar n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite H.               (* exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if negacion false &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      simpl.                   (* exists k : nat, S n&amp;#039; = doble k *)&lt;br /&gt;
      destruct HI as [k&amp;#039; Hk&amp;#039;]. (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = false&lt;br /&gt;
                                  k&amp;#039; : nat&lt;br /&gt;
                                  Hk&amp;#039; : n&amp;#039; = S (doble k&amp;#039;)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, S n&amp;#039; = doble k *)&lt;br /&gt;
      exists (1 + k&amp;#039;).              (* S n&amp;#039; = doble (1 + k&amp;#039;) *)&lt;br /&gt;
      rewrite Hk&amp;#039;.             (* S (S (doble k&amp;#039;)) = doble (1 + k&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.2. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        esPar n = true &amp;lt;-&amp;gt; exists k, n = doble k.&lt;br /&gt;
&lt;br /&gt;
   Es decir, que la computación booleana (esPar n) refleja la&lt;br /&gt;
   proposición (exists k, n = doble k).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_bool_prop:&lt;br /&gt;
  forall n : nat,&lt;br /&gt;
    esPar n = true &amp;lt;-&amp;gt; exists k, n = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true &amp;lt;-&amp;gt; (exists k : nat, n = doble k) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                       (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true -&amp;gt; exists k : nat, n = doble k *)&lt;br /&gt;
    intros H.             (* n : nat                           &lt;br /&gt;
                             H : esPar n = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             exists k : nat, n = doble k *)&lt;br /&gt;
    destruct&lt;br /&gt;
      (esPar_doble_aux n) &lt;br /&gt;
      as [k Hk].          (* n : nat&lt;br /&gt;
                             H : esPar n = true&lt;br /&gt;
                             k : nat&lt;br /&gt;
                             Hk : n = (if esPar n then doble k else S (doble k))&lt;br /&gt;
                             ============================&lt;br /&gt;
                             exists k0 : nat, n = doble k0 *)&lt;br /&gt;
    rewrite Hk.           (* exists k0 : nat, &lt;br /&gt;
                              (if esPar n &lt;br /&gt;
                               then doble k &lt;br /&gt;
                               else S (doble k)) &lt;br /&gt;
                              = doble k0 *)&lt;br /&gt;
    rewrite H.            (* exists k0 : nat, doble k = doble k0 *)&lt;br /&gt;
    exists k.                  (* doble k = doble k *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                       (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (exists k : nat, n = doble k) -&amp;gt; esPar n = true *)&lt;br /&gt;
    intros [k Hk].        (* n, k : nat&lt;br /&gt;
                             Hk : n = doble k&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true *)&lt;br /&gt;
    rewrite Hk.           (* esPar (doble k) = true *)&lt;br /&gt;
    apply esPar_doble.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.3. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true &amp;lt;-&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_bool_prop:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true &amp;lt;-&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true &amp;lt;-&amp;gt; n = m *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                           (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true -&amp;gt; n = m *)&lt;br /&gt;
    apply iguales_nat_true.&lt;br /&gt;
  -                           (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = m -&amp;gt; iguales_nat n m = true *)&lt;br /&gt;
    intros H.                 (* n, m : nat&lt;br /&gt;
                                 H : n = m&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true *)&lt;br /&gt;
    rewrite H.                (* iguales_nat m m = true *)&lt;br /&gt;
    rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.4. Definir la función es_primo_par tal que &lt;br /&gt;
   (es_primo_par n) es verifica si n es un primo par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fail Definition es_primo_par n :=&lt;br /&gt;
  if n = 2&lt;br /&gt;
  then true&lt;br /&gt;
  else false.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Definition es_primo_par n :=&lt;br /&gt;
  if iguales_nat n 2&lt;br /&gt;
  then true&lt;br /&gt;
  else false.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.1. Demostrar que&lt;br /&gt;
      exists k : nat, 1000 = doble k.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000: exists k : nat, 1000 = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  exists 500.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.2. Demostrar que&lt;br /&gt;
      esPar 1000 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000&amp;#039; : esPar 1000 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.3. Demostrar que&lt;br /&gt;
      exists k : nat, 1000 = doble k.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000&amp;#039;&amp;#039;: exists k : nat, 1000 = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply esPar_bool_prop. (* esPar 1000 = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas. &lt;br /&gt;
   1. En la proposicional se necesita proporcionar un testipo.&lt;br /&gt;
   2. En la booleano se calcula sin testigo.&lt;br /&gt;
   3, Se puede demostrar la proposional usando la equivalencia con la&lt;br /&gt;
      booleana sin necesidad de testigo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.2.1. Demostrar que&lt;br /&gt;
      forall x y : bool,&lt;br /&gt;
        x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_verdad_syss:&lt;br /&gt;
  forall x y : bool,&lt;br /&gt;
    x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.             (* x, y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true *)&lt;br /&gt;
  destruct x.             &lt;br /&gt;
  -                       (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; true = true /\ y = true *)&lt;br /&gt;
    destruct y.           &lt;br /&gt;
    +                     (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; true = true &amp;lt;-&amp;gt; true = true /\ true=true *)&lt;br /&gt;
      simpl.              (* true = true &amp;lt;-&amp;gt; true = true /\ true = true *)&lt;br /&gt;
      split.              &lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true -&amp;gt; true = true /\ true = true *)&lt;br /&gt;
        apply conj_intro. (* true = true *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ true = true -&amp;gt; true = true *)&lt;br /&gt;
        apply conj_e1.&lt;br /&gt;
    +                     (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; false = true &amp;lt;-&amp;gt; true=true /\ false=true *)&lt;br /&gt;
      simpl.              (* false = true &amp;lt;-&amp;gt; true = true /\ false = true *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true -&amp;gt; true = true /\ false = true *)&lt;br /&gt;
        intros H.         (* H : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ false = true *)&lt;br /&gt;
        inversion H.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ false = true -&amp;gt; false = true *)&lt;br /&gt;
        intros [H1 H2].   (* H1 : true = true&lt;br /&gt;
                             H2 : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                       (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; false = true /\ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                     (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false &amp;amp;&amp;amp; y = true -&amp;gt; false = true /\ y = true *)&lt;br /&gt;
      simpl.              (* false = true -&amp;gt; false = true /\ y = true *)&lt;br /&gt;
      intros H.           (* y : bool&lt;br /&gt;
                             H : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true /\ y = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true /\ y = true -&amp;gt; false &amp;amp;&amp;amp; y = true *)&lt;br /&gt;
      simpl.              (* false = true /\ y = true -&amp;gt; false = true *)&lt;br /&gt;
      intros [H1 H2].     (* y : bool&lt;br /&gt;
                             H1 : false = true&lt;br /&gt;
                             H2 : y = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.2.2. Demostrar que&lt;br /&gt;
      forall x y : bool,&lt;br /&gt;
        x || y = true &amp;lt;-&amp;gt; x = true \/ y = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma dist_verdad_syss:&lt;br /&gt;
  forall x y : bool,&lt;br /&gt;
    x || y = true &amp;lt;-&amp;gt; x = true \/ y = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.           (* x, y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           x || y = true &amp;lt;-&amp;gt; x = true \/ y = true *)&lt;br /&gt;
  destruct x.&lt;br /&gt;
  -                     (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true || y = true &amp;lt;-&amp;gt; true = true \/ y = true *)&lt;br /&gt;
    simpl.              (* true = true &amp;lt;-&amp;gt; true = true \/ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true -&amp;gt; true = true \/ y = true *)&lt;br /&gt;
      apply disy_intro. &lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true \/ y = true -&amp;gt; true = true *)&lt;br /&gt;
      intros.           (* y : bool&lt;br /&gt;
                           H : true = true \/ y = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                     (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false || y = true &amp;lt;-&amp;gt; false = true \/ y = true *)&lt;br /&gt;
    simpl.              (* y = true &amp;lt;-&amp;gt; false = true \/ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true -&amp;gt; false = true \/ y = true *)&lt;br /&gt;
      destruct y.&lt;br /&gt;
      *                 (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true -&amp;gt; false = true \/ true = true *)&lt;br /&gt;
        intros.         (* H : true = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true \/ true = true *)&lt;br /&gt;
        right.          (* true = true *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                 (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; false = true \/ false = true *)&lt;br /&gt;
        apply disy_intro.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true \/ y = true -&amp;gt; y = true *)&lt;br /&gt;
      intros [H1 | H2].&lt;br /&gt;
      *                 (* y : bool&lt;br /&gt;
                           H1 : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true *)&lt;br /&gt;
        inversion H1.&lt;br /&gt;
      *                 (* y : bool&lt;br /&gt;
                           H2 : y = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
        &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.3. Demostrar que&lt;br /&gt;
      forall x y : nat,&lt;br /&gt;
        iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_falso_syss:&lt;br /&gt;
  forall x y : nat,&lt;br /&gt;
    iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.                           (* x, y : nat&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
  destruct (iguales_nat x y) eqn:H.&lt;br /&gt;
  -                                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = true&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    rewrite iguales_nat_bool_prop in H. (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    rewrite H.                          (* true = false &amp;lt;-&amp;gt; y &amp;lt;&amp;gt; y *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false -&amp;gt; y &amp;lt;&amp;gt; y *)&lt;br /&gt;
      intros H1.                        (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : true = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           y &amp;lt;&amp;gt; y *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           y &amp;lt;&amp;gt; y -&amp;gt; true = false *)&lt;br /&gt;
      intros H1.                        (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : y &amp;lt;&amp;gt; y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false *)&lt;br /&gt;
      exfalso.                          (* False *)&lt;br /&gt;
      unfold not in H1.                 (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : y = y -&amp;gt; False&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      apply H1.                         (* y = y *)&lt;br /&gt;
      apply eq_refl.&lt;br /&gt;
  -                                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false -&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
      unfold not.                       (* false = false -&amp;gt; x = y -&amp;gt; False *)&lt;br /&gt;
      intros H1 H2.                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      rewrite H2 in H.                  (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat y y = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      rewrite iguales_nat_refl in H.    (* x, y : nat&lt;br /&gt;
                                           H : true = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           x &amp;lt;&amp;gt; y -&amp;gt; false = false *)&lt;br /&gt;
      intros.                           (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           H0 : x &amp;lt;&amp;gt; y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.4.1. Definir la función &lt;br /&gt;
      iguales_lista {A : Type} (i : A -&amp;gt; A -&amp;gt; bool) (xs ys : list A)&lt;br /&gt;
   tal que (iguales_lists xs ys) se verifica si los correspondientes&lt;br /&gt;
   elementos de las listas xs e ys son iguales respecto de la relación&lt;br /&gt;
   de igualdad i.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_lista {A : Type} (i : A -&amp;gt; A -&amp;gt; bool) (xs ys : list A) : bool :=&lt;br /&gt;
  match xs, ys with&lt;br /&gt;
  | nil, nil            =&amp;gt; true&lt;br /&gt;
  | x&amp;#039; ::xs&amp;#039;, y&amp;#039; :: ys&amp;#039; =&amp;gt; i x&amp;#039; y&amp;#039; &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039;&lt;br /&gt;
  | _, _                =&amp;gt; false                          &lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.4.2. Demostrar que&lt;br /&gt;
      forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
        (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
        forall xs ys, iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs = ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_CN:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, iguales_lista i xs ys = true -&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs.                  (* A : Type&lt;br /&gt;
                                       i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                       H : forall x y : A, &lt;br /&gt;
                                            i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                       xs : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i xs ys = true -&amp;gt; xs=ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HIxs&amp;#039;].&lt;br /&gt;
  -                                 (* A : Type&lt;br /&gt;
                                       i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                       H : forall x y : A, &lt;br /&gt;
                                            i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i [ ] ys = true -&amp;gt; &lt;br /&gt;
                                        [ ] = ys *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                               (* iguales_lista i [ ] [ ] = true -&amp;gt; &lt;br /&gt;
                                       [ ] = [ ] *)&lt;br /&gt;
      intros.                       (*   H0 : iguales_lista i [ ] [ ] = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       [ ] = [ ] *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                               (* y : A&lt;br /&gt;
                                       ys&amp;#039; : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       iguales_lista i [ ] (y :: ys&amp;#039;) = true &lt;br /&gt;
                                       -&amp;gt; [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      simpl.                        (* false = true -&amp;gt; [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      intros H1.                    (* H1 : false = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                                 (* x : A&lt;br /&gt;
                                       xs&amp;#039; : list A&lt;br /&gt;
                                       HIxs&amp;#039; : forall ys : list A, &lt;br /&gt;
                                                iguales_lista i xs&amp;#039; ys = true &lt;br /&gt;
                                                -&amp;gt; xs&amp;#039; = ys&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i (x :: xs&amp;#039;) ys = true &lt;br /&gt;
                                        -&amp;gt; x :: xs&amp;#039; = ys *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                               (* iguales_lista i (x :: xs&amp;#039;) [ ] = true &lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      simpl.                        (* false = true -&amp;gt; x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      intros H1.                    (* H1 : false = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                               (* y : A&lt;br /&gt;
                                       ys&amp;#039; : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       iguales_lista i (x::xs&amp;#039;) (y::ys&amp;#039;) = true&lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      simpl.                        (* i x y &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      intros H1.                    (* H1 : i x y &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039; = &lt;br /&gt;
                                            true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      apply conj_verdad_syss in H1. (* H1 : i x y = true /\ &lt;br /&gt;
                                            iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      destruct H1 as [H2 H3].       (* H2 : i x y = true&lt;br /&gt;
                                       H3 : iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      f_equal.&lt;br /&gt;
      *                             (* x = y *)&lt;br /&gt;
        apply H.                    (* i x y = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
      *                             (* xs&amp;#039; = ys&amp;#039; *)&lt;br /&gt;
        apply HIxs&amp;#039;.                (* iguales_lista i xs&amp;#039; ys&amp;#039; = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_CS:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, xs = ys -&amp;gt; iguales_lista i xs ys = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs.                (* A : Type&lt;br /&gt;
                                     i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                     H : forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                     xs : list A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall ys : &lt;br /&gt;
                                      list A, xs = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i xs ys = true *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HIxs&amp;#039;]. &lt;br /&gt;
  -                               (* forall ys : &lt;br /&gt;
                                      list A, [ ] = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i [ ] ys = true *)&lt;br /&gt;
    intros ys H1.                 (* ys : list A&lt;br /&gt;
                                     H1 : [ ] = ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     iguales_lista i [ ] ys = true *)&lt;br /&gt;
    rewrite &amp;lt;- H1.                 (* iguales_lista i [ ] [ ] = true *)&lt;br /&gt;
    simpl.                        (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                               (* x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HIxs&amp;#039; : forall ys : &lt;br /&gt;
                                              list A, xs&amp;#039; = ys -&amp;gt; &lt;br /&gt;
                                              iguales_lista i xs&amp;#039; ys = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall ys : &lt;br /&gt;
                                      list A, x :: xs&amp;#039; = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i (x :: xs&amp;#039;) ys = true *)&lt;br /&gt;
    intros ys H1.                 (* ys : list A&lt;br /&gt;
                                     H1 : x :: xs&amp;#039; = ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     iguales_lista i (x :: xs&amp;#039;) ys = true *)&lt;br /&gt;
    rewrite &amp;lt;-H1.                  (* iguales_lista i (x::xs&amp;#039;) (x::xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                        (* i x x &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    apply conj_verdad_syss.       (* i x x = true /\ &lt;br /&gt;
                                     iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                             (* i x x = true *)&lt;br /&gt;
      apply H.                    (* x = x *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                             (* iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
      apply HIxs&amp;#039;.                (* xs&amp;#039; = xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_syss:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs ys.              (* A : Type&lt;br /&gt;
                                      i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                      H : forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                      xs, ys : list A&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs=ys *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                                (* iguales_lista i xs ys = true -&amp;gt; xs = ys *)&lt;br /&gt;
    apply iguales_lista_verdad_CN. (* forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                                (* xs = ys -&amp;gt; iguales_lista i xs ys = true *)&lt;br /&gt;
    apply iguales_lista_verdad_CS. (* forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y *)&lt;br /&gt;
    apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.5. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
        todos p xs = true &amp;lt;-&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_CN:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    todos p xs = true -&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.                 (* X : Type&lt;br /&gt;
                                    p : X -&amp;gt; bool&lt;br /&gt;
                                    xs : list X&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    todos p xs = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].&lt;br /&gt;
  -                              (* todos p [ ] = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) [ ] *)&lt;br /&gt;
    simpl.                       (* true = true -&amp;gt; True *)&lt;br /&gt;
    intros.                      (* H : true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    True *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* x&amp;#039; : X&lt;br /&gt;
                                    xs&amp;#039; : list X&lt;br /&gt;
                                    HI : todos p xs&amp;#039; = true -&amp;gt; &lt;br /&gt;
                                         Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    todos p (x&amp;#039; :: xs&amp;#039;) = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) (x&amp;#039;::xs&amp;#039;) *)&lt;br /&gt;
    simpl.                       (* p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true -&amp;gt;&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    intros H.                    (* H : p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    apply conj_verdad_syss in H. (* H :p x&amp;#039; = true /\ todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    destruct H as [H1 H2].       (* H1 : p x&amp;#039; = true&lt;br /&gt;
                                    H2 : todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                            (* p x&amp;#039; = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
      apply HI.                  (* todos p xs&amp;#039; = true *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_CS:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    Todos (fun x =&amp;gt; p x = true) xs -&amp;gt; todos p xs = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.                (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) xs -&amp;gt; &lt;br /&gt;
                                   todos p xs = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* Todos (fun x : X =&amp;gt; p x = true) [ ] -&amp;gt; &lt;br /&gt;
                                   todos p [ ] = true *)&lt;br /&gt;
    simpl.                      (* True -&amp;gt; true = true *)&lt;br /&gt;
    intros.                     (* H : True&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        todos p xs&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) (x&amp;#039; :: xs&amp;#039;) &lt;br /&gt;
                                   -&amp;gt; todos p (x&amp;#039; :: xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                      (* p x&amp;#039; = true /\ &lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; -&amp;gt;&lt;br /&gt;
                                   p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true *)&lt;br /&gt;
    intros [H1 H2].             (* H1 : p x&amp;#039; = true&lt;br /&gt;
                                   H2 : Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true *)&lt;br /&gt;
    apply conj_verdad_syss.     (* p x&amp;#039; = true /\ todos p xs&amp;#039; = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                           (* p x&amp;#039; = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                           (* todos p xs&amp;#039; = true *)&lt;br /&gt;
      apply HI.                 (* Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_syss:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    todos p xs = true &amp;lt;-&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.           (* X : Type&lt;br /&gt;
                              p : X -&amp;gt; bool&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              ============================&lt;br /&gt;
                              todos p xs = true &amp;lt;-&amp;gt; &lt;br /&gt;
                              Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                        (* todos p xs = true -&amp;gt; &lt;br /&gt;
                              Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
    apply todos_verdad_CN. &lt;br /&gt;
  -                        (* Todos (fun x : X =&amp;gt; p x = true) xs -&amp;gt; &lt;br /&gt;
                              todos p xs = true *)&lt;br /&gt;
    apply todos_verdad_CS.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.3. Lógica clásica vs. constructiva  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.1. Definir la proposicion&lt;br /&gt;
      tercio_excluso&lt;br /&gt;
   que afirma que  (forall P : Prop, P \/ ~ P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Definition tercio_excluso : Prop := forall P : Prop,&lt;br /&gt;
  P \/ ~ P.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La proposión tercio_excluso no es demostrable en Coq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.2. Demostrar que&lt;br /&gt;
      forall (P : Prop) (b : bool),&lt;br /&gt;
        (P &amp;lt;-&amp;gt; b = true) -&amp;gt; P \/ ~ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_exluso_restringido :&lt;br /&gt;
  forall (P : Prop) (b : bool),&lt;br /&gt;
    (P &amp;lt;-&amp;gt; b = true) -&amp;gt; P \/ ~ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P [] H.  &lt;br /&gt;
  -               (* P : Prop&lt;br /&gt;
                     H : P &amp;lt;-&amp;gt; true = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     P \/ ~ P *)&lt;br /&gt;
    left.         (* P *)&lt;br /&gt;
    rewrite H.    (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* P : Prop&lt;br /&gt;
                     H : P &amp;lt;-&amp;gt; false = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     P \/ ~ P *)&lt;br /&gt;
    right.        (* ~ P *)&lt;br /&gt;
    rewrite H.    (* false &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H1.    (* H1 : false = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
    inversion H1. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        n = m \/ n &amp;lt;&amp;gt; m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_exluso_restringido_eq:&lt;br /&gt;
  forall (n m : nat),&lt;br /&gt;
    n = m \/ n &amp;lt;&amp;gt; m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                      (* n, m : nat&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      n = m \/ n &amp;lt;&amp;gt; m *)&lt;br /&gt;
  apply (tercio_exluso_restringido &lt;br /&gt;
           (n = m)&lt;br /&gt;
           (iguales_nat n m)).     (* n = m &amp;lt;-&amp;gt; iguales_nat n m = true *)&lt;br /&gt;
  symmetry.                        (* iguales_nat n m = true &amp;lt;-&amp;gt; n = m *)&lt;br /&gt;
  apply iguales_nat_bool_prop.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En Coq no se puede demostrar el principio del tercio exluso.&lt;br /&gt;
   2. Las demostraciones de las fórmulas existenciales tienen que&lt;br /&gt;
      proporcionar un testigo.&lt;br /&gt;
   2. la lógica de Coq es constructiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.1. Demostrar que&lt;br /&gt;
      forall (P : Prop),&lt;br /&gt;
        ~ ~ (P \/ ~ P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_irrefutable:&lt;br /&gt;
  forall (P : Prop),&lt;br /&gt;
    ~ ~ (P \/ ~ P).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P.   (* P : Prop&lt;br /&gt;
                 ============================&lt;br /&gt;
                 ~ ~ (P \/ ~ P) *)&lt;br /&gt;
  unfold not. (* (P \/ (P -&amp;gt; False) -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros H.   (* H : P \/ (P -&amp;gt; False) -&amp;gt; False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply H.    (* P \/ (P -&amp;gt; False) *)&lt;br /&gt;
  right.      (* P -&amp;gt; False *)&lt;br /&gt;
  intro H1.   (* H1 : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply H.    (* P \/ (P -&amp;gt; False) *)&lt;br /&gt;
  left.       (* P *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El teorema anterior garantiza que añadir el tercio excluso como&lt;br /&gt;
   axioma no provoca contradicción.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.2. Demostrar que&lt;br /&gt;
      tercio_excluso -&amp;gt;&lt;br /&gt;
      forall (X : Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
        ~ (exists x, ~ P x) -&amp;gt; (forall x, P x).&lt;br /&gt;
&lt;br /&gt;
   Nota. La condición del tercio_excluso es necesaria.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem no_existe_no:&lt;br /&gt;
  tercio_excluso -&amp;gt;&lt;br /&gt;
  forall (X : Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
    ~ (exists x, ~ P x) -&amp;gt; (forall x, P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 X P H2 x.          (* H1 : tercio_excluso&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  P : X -&amp;gt; Prop&lt;br /&gt;
                                  H2 : ~ (exists x : X, ~ P x)&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
  unfold tercio_excluso in H1. (* H1 : forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  assert (P x \/ ~ P x).&lt;br /&gt;
  -                            (* P x \/ ~ P x *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                            (* H : P x \/ ~ P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
    destruct H as [H3 | H4].&lt;br /&gt;
    +                          (* x : X&lt;br /&gt;
                                  H3 : P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                          (* x : X&lt;br /&gt;
                                  H4 : ~ P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
      exfalso.                 (* False *)&lt;br /&gt;
      apply H2.                (* exists x0 : X, ~ P x0 *)&lt;br /&gt;
      exists x.                     (* ~ P x *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.1. En este ejercico se van a demostrar 4 formas&lt;br /&gt;
   equivalentes del principio del tercio excluso. &lt;br /&gt;
&lt;br /&gt;
   Sea peirce la proposición definida por&lt;br /&gt;
      Definition peirce: Prop := forall P Q : Prop,&lt;br /&gt;
        ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; peirce &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition peirce: Prop := forall P Q : Prop,&lt;br /&gt;
  ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_peirce_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; peirce.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.     (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                (forall P : Prop, P \/ ~ P) -&amp;gt; peirce *)&lt;br /&gt;
  unfold peirce.             (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P *)&lt;br /&gt;
  intros H1 P Q H2.          (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                P, Q : Prop&lt;br /&gt;
                                H2 : (P -&amp;gt; Q) -&amp;gt; P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                          (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* H : P \/ ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                        (* H3 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                        (* H4 : ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
      apply H2.              (* P -&amp;gt; Q *)&lt;br /&gt;
      intros H5.             (* H5 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
      exfalso.               (* False *)&lt;br /&gt;
      apply H4.              (* P *)&lt;br /&gt;
      apply H5.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_peirce_L2:&lt;br /&gt;
  peirce -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold peirce.         (* &lt;br /&gt;
                            ============================&lt;br /&gt;
                            (forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                            tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso. (* (forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                            forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H P.            (* H : forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P&lt;br /&gt;
                            P : Prop&lt;br /&gt;
                            ============================&lt;br /&gt;
                            P \/ ~ P *)&lt;br /&gt;
  apply H with (Q := False). (* (P \/ ~ P -&amp;gt; False) -&amp;gt; P \/ ~ P *)&lt;br /&gt;
  intros H1.             (* H1 : P \/ ~ P -&amp;gt; False&lt;br /&gt;
                            ============================&lt;br /&gt;
                            P \/ ~ P *)&lt;br /&gt;
  right.                 (* ~ P *)&lt;br /&gt;
  unfold not.            (* P -&amp;gt; False *)&lt;br /&gt;
  intros H2.             (* H2 : P&lt;br /&gt;
                            ============================&lt;br /&gt;
                            False *)&lt;br /&gt;
  apply H1.              (* P \/ ~ P *)&lt;br /&gt;
  left.                  (* P *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_peirce:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; peirce.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                                 (* &lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       tercio_excluso -&amp;gt; peirce *)&lt;br /&gt;
    apply tercio_excluso_peirce_L1. &lt;br /&gt;
  -                                 (* &lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       peirce -&amp;gt; tercio_excluso *)&lt;br /&gt;
    apply tercio_excluso_peirce_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.2. Sea eliminacion_doble_negacion la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition eliminacion_doble_negacion: Prop := forall P : Prop,&lt;br /&gt;
        ~~P -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; eliminacion_doble_negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition eliminacion_doble_negacion: Prop := forall P : Prop,&lt;br /&gt;
  ~~P -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; eliminacion_doble_negacion.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.             (* &lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                        eliminacion_doble_negacion *)&lt;br /&gt;
  unfold eliminacion_doble_negacion. (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                        forall P : Prop, ~ ~ P -&amp;gt; P *)&lt;br /&gt;
  intros H1 P H2.                    (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                        P : Prop&lt;br /&gt;
                                        H2 : ~ ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                                  (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                  (* H : P \/ ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
    destruct H as [H3 | H4].&lt;br /&gt;
    +                                (* H2 : ~ ~ P&lt;br /&gt;
                                        H3 : P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                                (* H4 : ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
      exfalso.                       (* False *)&lt;br /&gt;
      apply H2.                      (* ~ P *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion_L2:&lt;br /&gt;
  eliminacion_doble_negacion -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold eliminacion_doble_negacion. (* &lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        (forall P : Prop, ~ ~ P -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                                        tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.             (* (forall P : Prop, ~ ~ P -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                                        forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H P.                        (* H : forall P : Prop, ~ ~ P -&amp;gt; P&lt;br /&gt;
                                        P : Prop&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P \/ ~ P *)&lt;br /&gt;
  apply H.                           (* ~ ~ (P \/ ~ P) *)&lt;br /&gt;
  apply tercio_excluso_irrefutable.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; eliminacion_doble_negacion.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_eliminacion_doble_negacion_L1.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_eliminacion_doble_negacion_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.3. Sea morgan_no_no la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition de_morgan_no_no: Prop :=&lt;br /&gt;
        forall P Q : Prop, ~(~P /\ ~Q) -&amp;gt; P \/ Q.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; morgan_no_no&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition de_morgan_no_no: Prop :=&lt;br /&gt;
  forall P Q : Prop, ~(~P /\ ~Q) -&amp;gt; P \/ Q.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; de_morgan_no_no.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.     (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                de_morgan_no_no *)&lt;br /&gt;
  unfold de_morgan_no_no.    (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q *)&lt;br /&gt;
  intros H1 P Q H2.          (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                P, Q : Prop&lt;br /&gt;
                                H2 : ~ (~ P /\ ~ Q)&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                          (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* H : P \/ ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                        (* H2 : ~ (~ P /\ ~ Q)&lt;br /&gt;
                                H3 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
      left.                  (* P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                        (* H4 : ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
      right.                 (* Q *)&lt;br /&gt;
      assert (Q \/ ~ Q).&lt;br /&gt;
      *                      (* Q \/ ~ Q *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                      (* H : Q \/ ~ Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
        destruct H as [H5 | H6].&lt;br /&gt;
        --                   (* H5 : Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
          apply H5.&lt;br /&gt;
        --                   (* H6 : ~ Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
          exfalso.           (* False *)&lt;br /&gt;
          apply H2.          (* ~ P /\ ~ Q *)&lt;br /&gt;
          split.&lt;br /&gt;
          ++                 (* ~ P *)&lt;br /&gt;
            apply H4.&lt;br /&gt;
          ++                 (* ~ Q *)&lt;br /&gt;
            apply H6.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no_L2:&lt;br /&gt;
  de_morgan_no_no -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold de_morgan_no_no. (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             (forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q) -&amp;gt; &lt;br /&gt;
                             tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.  (* (forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q) -&amp;gt; &lt;br /&gt;
                             forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H1 P.            (* H1 : forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q&lt;br /&gt;
                             P : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ ~ P *)&lt;br /&gt;
  apply H1.               (* ~ (~ P /\ ~ ~ P) *)&lt;br /&gt;
  intros H2.              (* H2 : ~ P /\ ~ ~ P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             False *)&lt;br /&gt;
  destruct H2 as (H3,H4). (* H3 : ~ P&lt;br /&gt;
                             H4 : ~ ~ P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             False *)&lt;br /&gt;
  apply H4.               (* ~ P *)&lt;br /&gt;
  apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; de_morgan_no_no.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_de_morgan_no_no_L1.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_de_morgan_no_no_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.4. Sea condicional_a_disyuncion la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition condicional_a_disyuncion: Prop :=&lt;br /&gt;
        forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; (~P \/ Q).&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; morgan_no_no&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition condicional_a_disyuncion: Prop :=&lt;br /&gt;
  forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; (~P \/ Q).&lt;br /&gt;
&lt;br /&gt;
Lemma tercio_excluso_equiv_condicional_a_disyuncion_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; condicional_a_disyuncion.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.           (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                      condicional_a_disyuncion *)&lt;br /&gt;
  unfold condicional_a_disyuncion. (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                      forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q *)&lt;br /&gt;
  intros H1 P Q H2.                (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                      P, Q : Prop&lt;br /&gt;
                                      H2 : P -&amp;gt; Q&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                                (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                (* H : P \/ ~ P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                              (* H3 : P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
      right.                       (* Q *)&lt;br /&gt;
      apply H2.                    (* P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                              (* H4 : ~ P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
      left.                        (* ~ P *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma tercio_excluso_equiv_condicional_a_disyuncion_L2:&lt;br /&gt;
  condicional_a_disyuncion -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold condicional_a_disyuncion. (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      (forall P Q:Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q) &lt;br /&gt;
                                      -&amp;gt; tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.           (* (forall P Q:Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q) &lt;br /&gt;
                                      -&amp;gt; forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H1 P.                     (* H1 : forall P Q : Prop, &lt;br /&gt;
                                            (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q&lt;br /&gt;
                                      P : Prop&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      P \/ ~ P *)&lt;br /&gt;
  apply disy_conmutativa.          (* ~ P \/ P *)&lt;br /&gt;
  apply H1.                        (* P -&amp;gt; P *)&lt;br /&gt;
  intros.                          (* H : P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_condicional_a_disyuncion:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; condicional_a_disyuncion.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  - apply tercio_excluso_equiv_condicional_a_disyuncion_L1.&lt;br /&gt;
  - apply tercio_excluso_equiv_condicional_a_disyuncion_L2.&lt;br /&gt;
Qed.    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Logic.html Logic in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_6:_L%C3%B3gica_en_Coq&amp;diff=72</id>
		<title>Tema 6: Lógica en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_6:_L%C3%B3gica_en_Coq&amp;diff=72"/>
		<updated>2018-08-20T10:45:26Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este capítulo se amplía el campo de aplicación de Coq para todas las conectivas y cuantificadores de la lógica de primer orden.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T6_Logica.v|T6_Logica.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T6: Lógica en Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T5_Tacticas.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. Introducción&lt;br /&gt;
   2. Conectivas lógicas &lt;br /&gt;
      1. Conjunción &lt;br /&gt;
      2. Disyunción  &lt;br /&gt;
      3. Falsedad y negación  &lt;br /&gt;
      4. Verdad&lt;br /&gt;
      5. Equivalencia lógica&lt;br /&gt;
      6. Cuantificación existencial  &lt;br /&gt;
   3. Programación con proposiciones &lt;br /&gt;
   4. Aplicando teoremas a argumentos &lt;br /&gt;
   5. Coq vs. teoría de conjuntos &lt;br /&gt;
      1. Extensionalidad funcional&lt;br /&gt;
      2. Proposiciones y booleanos  &lt;br /&gt;
      3. Lógica clásica vs. constructiva  &lt;br /&gt;
   Bibliografía&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Introducción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      3 = 3.&lt;br /&gt;
      3 = 4.&lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
      forall n : nat, n = 2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check 3 = 3.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check 3 = 4.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check forall n m : nat, n + m = m + n.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check forall n : nat, n = 2.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El tipo de las fórmulas es Prop.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Demostrar que 2 más dos es 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_2_y_2:&lt;br /&gt;
  2 + 2 = 4.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Usa la proposición &amp;#039;2 + 2 = 4&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la proposición &lt;br /&gt;
      prop_suma: Prop&lt;br /&gt;
   que afirma que la suma de 2 y 2 es 4. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prop_suma: Prop := 2 + 2 = 4.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Calcular el tipo de prop_suma&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check prop_suma.&lt;br /&gt;
(* ===&amp;gt; prop_suma : Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Usando prop_suma, demostrar que la suma de 2 y 2 es 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_suma_es_verdadera:&lt;br /&gt;
  prop_suma.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Definir la proposición &lt;br /&gt;
      es_tres (n : nat) : Prop&lt;br /&gt;
   tal que (es_tres n) se verifica si n es el número 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition es_tres (n : nat) : Prop :=&lt;br /&gt;
  n = 3.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.2. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      es_tres.&lt;br /&gt;
      es_tres 3.&lt;br /&gt;
      es_tres 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres.&lt;br /&gt;
(* ===&amp;gt; nat -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres 3.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres 5.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Ejemplo de proposición parametrizada.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir la función&lt;br /&gt;
      inyectiva {A B : Type} (f : A -&amp;gt; B) : Prop :=&lt;br /&gt;
   tal que (inyectiva f) se verifica si f es inyectiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition inyectiva {A B : Type} (f : A -&amp;gt; B) : Prop :=&lt;br /&gt;
  forall x y : A, f x = f y -&amp;gt; x = y.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Demostrar que la funcion sucesor es inyectiva; es&lt;br /&gt;
   decir, &lt;br /&gt;
      inyectiva S.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma suc_iny: inyectiva S.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5. Calcular los tipos de las siguientes expresiones&lt;br /&gt;
      3 = 5.&lt;br /&gt;
      eq 3 5.&lt;br /&gt;
      eq 3.&lt;br /&gt;
      @eq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (3 = 5).&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check (eq 3 5).&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check (eq 3).&lt;br /&gt;
(* ===&amp;gt; nat -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check @eq.&lt;br /&gt;
(* ===&amp;gt; forall A : Type, A -&amp;gt; A -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. La expresión (x = y) es una abreviatura de (eq x y).&lt;br /&gt;
   2. Se escribe @eq en lugar de eq para ver los argumentos implícitos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Conectivas lógicas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.1. Conjunción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que&lt;br /&gt;
      3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ej_conjuncion: 3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.         &lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    3 + 4 = 7 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    2 * 2 = 4 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. El símbolo de conjunción se escribe con /\&lt;br /&gt;
   2. La táctica &amp;#039;split&amp;#039; sustituye el objetivo (P /\ Q) por los&lt;br /&gt;
   subobjetivos P y Q. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que&lt;br /&gt;
      forall A B : Prop, A -&amp;gt; B -&amp;gt; A /\ B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_intro: forall A B : Prop, A -&amp;gt; B -&amp;gt; A /\ B.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B HA HB. (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       A /\ B *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                 (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       A *)&lt;br /&gt;
    apply HA.&lt;br /&gt;
  -                 (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       B *)&lt;br /&gt;
    apply HB.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar, con con_intro, que&lt;br /&gt;
      3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ej_conjuncion&amp;#039;: 3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply conj_intro. &lt;br /&gt;
  -                 (* 3 + 4 = 7 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* 2 * 2 = 4 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.1. Demostrar que&lt;br /&gt;
      forall n m : nat, n + m = 0 -&amp;gt; n = 0 /\ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_conj:&lt;br /&gt;
  forall n m : nat, n + m = 0 -&amp;gt; n = 0 /\ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.                      (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        n = 0 /\ m = 0 *)&lt;br /&gt;
  apply conj_intro.&lt;br /&gt;
  -                                  (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        n = 0 *)&lt;br /&gt;
    destruct n.&lt;br /&gt;
    +                                (* m : nat&lt;br /&gt;
                                        H : 0 + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                (* n, m : nat&lt;br /&gt;
                                        H : S n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S n = 0 *)&lt;br /&gt;
      simpl in H.                    (* n, m : nat&lt;br /&gt;
                                        H : S (n + m) = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S n = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                                  (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        m = 0 *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                                (* n : nat&lt;br /&gt;
                                        H : n + 0 = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                (* n, m : nat&lt;br /&gt;
                                        H : n + S m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      rewrite suma_conmutativa in H. (* n, m : nat&lt;br /&gt;
                                        H : S m + n = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      simpl in H.                    (* n, m : nat&lt;br /&gt;
                                        H : S (m + n) = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.4. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2 :&lt;br /&gt;
  forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.          (* n, m : nat&lt;br /&gt;
                            H : n = 0 /\ m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  destruct H as [Hn Hm]. (* n, m : nat&lt;br /&gt;
                            Hn : n = 0&lt;br /&gt;
                            Hm : m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  rewrite Hn.            (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.            (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct H as [HA HB]&amp;#039; que  sustituye la&lt;br /&gt;
   hipótesis H de la forma (A /\ B) por las hipótesis HA (que afirma&lt;br /&gt;
   que A es verdad) y HB (que afirma que B es verdad).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.5. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2&amp;#039; :&lt;br /&gt;
  forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m [Hn Hm].    (* n, m : nat&lt;br /&gt;
                            Hn : n = 0&lt;br /&gt;
                            Hm : m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  rewrite Hn.            (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.            (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;intros x [HA HB]&amp;#039;, cuando el objetivo es de la&lt;br /&gt;
   forma (forall x, A /\ B -&amp;gt; C), introduce la variable x y las&lt;br /&gt;
   hipótesis HA y HB afirmando la certeza de A y de B, respectivamente.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.6. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 -&amp;gt; m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2&amp;#039;&amp;#039; :&lt;br /&gt;
  forall n m : nat, n = 0 -&amp;gt; m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m Hn Hm. (* n, m : nat&lt;br /&gt;
                       Hn : n = 0&lt;br /&gt;
                       Hm : m = 0&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n + m = 0 *)&lt;br /&gt;
  rewrite Hn.       (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.       (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.7. Demostrar que&lt;br /&gt;
      forall n m : nat, n + m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion3 :&lt;br /&gt;
  forall n m : nat, n + m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.                (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
  assert (H&amp;#039; : n = 0 /\ m = 0). &lt;br /&gt;
  -                            (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n = 0 /\ m = 0 *)&lt;br /&gt;
    apply ejercicio_conj.      (* n + m = 0 *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                            (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  H&amp;#039; : n = 0 /\ m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
    destruct H&amp;#039; as [Hn Hm].    (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  Hn : n = 0&lt;br /&gt;
                                  Hm : m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
    rewrite Hn.                (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.8. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_e1 : forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         P *)&lt;br /&gt;
  apply HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.2. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_e2: forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; Q.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q *)&lt;br /&gt;
  apply HQ.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.9. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; Q /\ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conj_conmutativa: forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; Q /\ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q /\ P *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                   (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q *)&lt;br /&gt;
    apply HQ.&lt;br /&gt;
  -                   (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.3. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        P /\ (Q /\ R) -&amp;gt; (P /\ Q) /\ R.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conj_asociativa : forall P Q R : Prop,&lt;br /&gt;
  P /\ (Q /\ R) -&amp;gt; (P /\ Q) /\ R.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R [HP [HQ HR]]. (* P, Q, R : Prop&lt;br /&gt;
                                HP : P&lt;br /&gt;
                                HQ : Q&lt;br /&gt;
                                HR : R&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (P /\ Q) /\ R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                          (* P /\ Q *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                        (* P *)&lt;br /&gt;
      apply HP.&lt;br /&gt;
    +                        (* Q *)&lt;br /&gt;
      apply HQ.&lt;br /&gt;
  -                          (* R *)&lt;br /&gt;
    apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;intros P Q R [HP [HQ HR]]&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.10. Calcular el tipo de la expresión&lt;br /&gt;
      and&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check and.&lt;br /&gt;
(* ===&amp;gt; and : Prop -&amp;gt; Prop -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. (x /\ y) es una abreviatura de (and x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.2. Disyunción  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Lemma disy_ej1:&lt;br /&gt;
  forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.&lt;br /&gt;
  destruct H as [Hn | Hm]. &lt;br /&gt;
  -                        (* n, m : nat&lt;br /&gt;
                              Hn : n = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * m = 0 *)&lt;br /&gt;
    rewrite Hn.            (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.           &lt;br /&gt;
  -                        (* n, m : nat&lt;br /&gt;
                              Hm : m = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * m = 0 *)&lt;br /&gt;
    rewrite Hm.            (* n * 0 = 0 *)&lt;br /&gt;
    rewrite &amp;lt;- mult_n_O.    (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Lemma disy_ej:&lt;br /&gt;
  forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m [Hn | Hm]. &lt;br /&gt;
  -                     (* n, m : nat&lt;br /&gt;
                           Hn : n = 0&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n * m = 0 *)&lt;br /&gt;
    rewrite Hn.         (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n, m : nat&lt;br /&gt;
                           Hm : m = 0&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n * m = 0 *)&lt;br /&gt;
    rewrite Hm.         (* n * 0 = 0 *)&lt;br /&gt;
    rewrite &amp;lt;- mult_n_O. (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. La táctica &amp;#039;destruct H as [Hn | Hm]&amp;#039;, cuando la hipótesis H es de&lt;br /&gt;
      la forma (A \/ B), la divide en dos casos: uno con hipótesis HA&lt;br /&gt;
      (afirmando la certeza de A) y otro con la hipótesis HB (afirmando&lt;br /&gt;
      la certeza de B).   &lt;br /&gt;
   2. La táctica &amp;#039;intros x [HA | HB]&amp;#039;, cuando el objetivo es de la&lt;br /&gt;
      forma (forall x, A \/ B -&amp;gt; C), intoduce la variable x y dos casos:&lt;br /&gt;
      uno con hipótesis HA (afirmando la certeza de A) y otro con la&lt;br /&gt;
      hipótesis HB (afirmando la certeza de B).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que&lt;br /&gt;
      forall A B : Prop, A -&amp;gt; A \/ B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma disy_intro: forall A B : Prop, A -&amp;gt; A \/ B.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B HA. (* A, B : Prop&lt;br /&gt;
                    HA : A&lt;br /&gt;
                    ============================&lt;br /&gt;
                    A \/ B *)&lt;br /&gt;
  left.          (* A *)&lt;br /&gt;
  apply HA.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;left&amp;#039; sustituye el objetivo de la forma (A \/ B)&lt;br /&gt;
   por A.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.3. Demostrar que&lt;br /&gt;
      forall n : nat, n = 0 \/ n = S (pred n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cero_o_sucesor:&lt;br /&gt;
  forall n : nat, n = 0 \/ n = S (pred n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    0 = 0 \/ 0 = S (Nat.pred 0) *)&lt;br /&gt;
    left.        (* 0 = 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* n : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    S n = 0 \/ S n = S (Nat.pred (S n)) *)&lt;br /&gt;
    right.       (* S n = S (Nat.pred (S n)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;right&amp;#039; sustituye el objetivo de la forma (A \/ B)&lt;br /&gt;
   por B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que&lt;br /&gt;
      forall n m, n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_eq_0 :&lt;br /&gt;
  forall n m, n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.          (* n, m : nat&lt;br /&gt;
                            H : n * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n = 0 \/ m = 0 *)&lt;br /&gt;
  destruct n as [|n&amp;#039;].&lt;br /&gt;
  -                      (* m : nat&lt;br /&gt;
                            H : 0 * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 = 0 \/ m = 0 *)&lt;br /&gt;
    left.                (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n&amp;#039;, m : nat&lt;br /&gt;
                            H : S n&amp;#039; * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ m = 0 *)&lt;br /&gt;
    destruct m as [|m&amp;#039;]. &lt;br /&gt;
    +                    (* n&amp;#039; : nat&lt;br /&gt;
                            H : S n&amp;#039; * 0 = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ 0 = 0 *)&lt;br /&gt;
      right.             (* 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                            H : S n&amp;#039; * S m&amp;#039; = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ S m&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.        (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                            H : S (m&amp;#039; + n&amp;#039; * S m&amp;#039;) = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ S m&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P \/ Q  -&amp;gt; Q \/ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem disy_conmutativa: forall P Q : Prop,&lt;br /&gt;
  P \/ Q  -&amp;gt; Q \/ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP | HQ]. &lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HP : P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q \/ P *)&lt;br /&gt;
    right.              (* P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HQ : Q&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q \/ P *)&lt;br /&gt;
    left.               (* Q *)&lt;br /&gt;
    apply HQ.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.4. Calcular el tipo de la expresión&lt;br /&gt;
      or&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check or.&lt;br /&gt;
(* ===&amp;gt; or : Prop -&amp;gt; Prop -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. (x \/ y) es una abreviatura de (or x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.3. Falsedad y negación  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module DefNot.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Definir la función&lt;br /&gt;
      not (P : Prop) : Prop&lt;br /&gt;
   tal que (not P) es la negación de P&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition not (P:Prop) : Prop :=&lt;br /&gt;
    P -&amp;gt; False.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Definir (~ x) como abreviatura de (not x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;~ x&amp;quot; := (not x) : type_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Esta es la forma como está definida la negación en Coq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End DefNot.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que&lt;br /&gt;
      forall (P:Prop),&lt;br /&gt;
        False -&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ex_falso_quodlibet: forall (P:Prop),&lt;br /&gt;
  False -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 P *)&lt;br /&gt;
  destruct H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. En latín, &amp;quot;ex falso quodlibet&amp;quot; significa &amp;quot;de lo falso (se&lt;br /&gt;
   sigue) cualquier cosa&amp;quot;. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.1. Demostrar que&lt;br /&gt;
      forall (P:Prop),&lt;br /&gt;
        ~ P -&amp;gt; (forall (Q:Prop), P -&amp;gt; Q).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact negacion_elim: forall (P:Prop),&lt;br /&gt;
  ~ P -&amp;gt; (forall (Q:Prop), P -&amp;gt; Q).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.     (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     forall P : Prop, (P -&amp;gt; False) -&amp;gt; forall Q : Prop, P -&amp;gt; Q *)&lt;br /&gt;
  intros P H1.    (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     ============================&lt;br /&gt;
                     forall Q : Prop, P -&amp;gt; Q *)&lt;br /&gt;
  intros Q H2.    (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     Q : Prop&lt;br /&gt;
                     H2 : P&lt;br /&gt;
                     ============================&lt;br /&gt;
                     Q *)&lt;br /&gt;
  apply H1 in H2. (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     Q : Prop&lt;br /&gt;
                     H2 : False&lt;br /&gt;
                     ============================&lt;br /&gt;
                     Q *)&lt;br /&gt;
  destruct H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que&lt;br /&gt;
      ~(0 = 1).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_no_es_uno: ~(0 = 1).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H.       (* H : 0 = 1&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La expresión (x &amp;lt;&amp;gt; y) es una abreviatura de ~(x = y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem cero_no_es_uno&amp;#039;: 0 &amp;lt;&amp;gt; 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H.       (* H : 0 = 1&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
  inversion H. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que&lt;br /&gt;
      ~ False&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem not_False :&lt;br /&gt;
  ~ False.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not. (* &lt;br /&gt;
                 ============================&lt;br /&gt;
                 False -&amp;gt; False *)&lt;br /&gt;
  intros H.   (* H : False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  destruct H. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        (P /\ ~P) -&amp;gt; Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem contradiccion_implica_cualquiera: forall P Q : Prop,&lt;br /&gt;
  (P /\ ~P) -&amp;gt; Q.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HNP]. (* P, Q : Prop&lt;br /&gt;
                          HP : P&lt;br /&gt;
                          HNP : ~ P&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  unfold not in HNP. (* P, Q : Prop&lt;br /&gt;
                          HP : P&lt;br /&gt;
                          HNP : P -&amp;gt; False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  apply HNP in HP. (* P, Q : Prop&lt;br /&gt;
                          HP : False&lt;br /&gt;
                          HNP : P -&amp;gt; False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  destruct HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.7. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        P -&amp;gt; ~~P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem doble_neg: forall P : Prop,&lt;br /&gt;
  P -&amp;gt; ~~P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 ~ ~ P *)&lt;br /&gt;
  unfold not. (* (P -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros G.   (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 G : P -&amp;gt; False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply G.    (* P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.2. Demostrar que&lt;br /&gt;
      forall (P Q : Prop),&lt;br /&gt;
        (P -&amp;gt; Q) -&amp;gt; (~Q -&amp;gt; ~P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem contrapositiva: forall (P Q : Prop),&lt;br /&gt;
  (P -&amp;gt; Q) -&amp;gt; (~Q -&amp;gt; ~P).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.          (* &lt;br /&gt;
                          ============================&lt;br /&gt;
                          forall P Q : Prop, &lt;br /&gt;
                            (P -&amp;gt; Q) -&amp;gt; (Q -&amp;gt; False) -&amp;gt; P -&amp;gt; False *)&lt;br /&gt;
  intros P Q H1 H2 H3. (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : P&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H1 in H3.      (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : Q&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H2 in H3.      (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.3. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        ~ (P /\ ~P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem no_contradiccion: forall P : Prop,&lt;br /&gt;
  ~ (P /\ ~P).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.       (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       forall P : Prop, P /\ (P -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros P [H1 H2]. (* P : Prop&lt;br /&gt;
                       H1 : P&lt;br /&gt;
                       H2 : P -&amp;gt; False&lt;br /&gt;
                       ============================&lt;br /&gt;
                       False *)&lt;br /&gt;
  apply H2.         (* P *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.8. Demostrar que&lt;br /&gt;
      forall b : bool,&lt;br /&gt;
        b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem no_verdadero_es_falso: forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] H.&lt;br /&gt;
  -                           (* H : true &amp;lt;&amp;gt; true&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = false *)&lt;br /&gt;
    unfold not in H.          (* H : true = true -&amp;gt; False&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = false *)&lt;br /&gt;
    apply ex_falso_quodlibet. (* H : true = true -&amp;gt; False&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 False *)&lt;br /&gt;
    apply H.                  (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* H : false &amp;lt;&amp;gt; true&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem no_verdadero_es_falso&amp;#039;: forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] H.&lt;br /&gt;
  -                  (* H : true &amp;lt;&amp;gt; true&lt;br /&gt;
                        ============================&lt;br /&gt;
                        true = false *)&lt;br /&gt;
    unfold not in H. (* H : true = true -&amp;gt; False&lt;br /&gt;
                        ============================&lt;br /&gt;
                        true = false *)&lt;br /&gt;
    exfalso.         (* H : true = true -&amp;gt; False&lt;br /&gt;
                        ============================&lt;br /&gt;
                        False *)&lt;br /&gt;
    apply H.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                  (* H : false &amp;lt;&amp;gt; true&lt;br /&gt;
                        ============================&lt;br /&gt;
                        false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas. &lt;br /&gt;
   1. Uso de &amp;#039;apply ex_falso_quodlibet&amp;#039; en la primera demostración.&lt;br /&gt;
   2. Uso de &amp;#039;exfalso&amp;#039; en la segunda demostración.&lt;br /&gt;
   3. La táctica &amp;#039;exfalso&amp;#039; sustituye el objetivo por falso. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.4. Verdad&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.1. Demostrar que la proposición True es verdadera.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma True_es_verdadera : True.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply I.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso del constructor I.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.5. Equivalencia lógica  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module DefIff.&lt;br /&gt;
&lt;br /&gt;
  (* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.1. Definir la función&lt;br /&gt;
      iff (P Q : Prop) : Prop&lt;br /&gt;
   tal que  (iff P Q) es la equivalencia de P y Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Definition iff (P Q : Prop) : Prop := (P -&amp;gt; Q) /\ (Q -&amp;gt; P).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.2. Definir (P &amp;lt;-&amp;gt; Q) como una abreviatura de (iff P Q). &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;P &amp;lt;-&amp;gt; Q&amp;quot; := (iff P Q)&lt;br /&gt;
                      (at level 95, no associativity)&lt;br /&gt;
                      : type_scope.&lt;br /&gt;
&lt;br /&gt;
End DefIff.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.3. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iff_sim : forall P Q : Prop,&lt;br /&gt;
  (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; P).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HPQ HQP]. (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q &amp;lt;-&amp;gt; P *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q -&amp;gt; P *)&lt;br /&gt;
    apply HQP.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; Q *)&lt;br /&gt;
    apply HPQ.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.4. Demostrar que&lt;br /&gt;
      forall b : bool,&lt;br /&gt;
        b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma not_true_iff_false : forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.                      (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                              (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true -&amp;gt; b = false *)&lt;br /&gt;
    apply no_verdadero_es_falso. &lt;br /&gt;
  -                              (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b = false -&amp;gt; b &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H.                    (* b : bool&lt;br /&gt;
                                    H : b = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true *)&lt;br /&gt;
    rewrite H.                   (* false &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H&amp;#039;.                   (* b : bool&lt;br /&gt;
                                    H : b = false&lt;br /&gt;
                                    H&amp;#039; : false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    False *)&lt;br /&gt;
    inversion H&amp;#039;.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.4. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        P &amp;lt;-&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma iff_refl_aux: forall P : Prop,&lt;br /&gt;
    P -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem iff_refl: forall P : Prop,&lt;br /&gt;
    P &amp;lt;-&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                     (* P : Prop&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; P *)&lt;br /&gt;
    apply iff_refl_aux. &lt;br /&gt;
  -                     (* P : Prop&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; P *)&lt;br /&gt;
    apply iff_refl_aux.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.5. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; R) -&amp;gt; (P &amp;lt;-&amp;gt; R).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iff_trans: forall P Q R : Prop,&lt;br /&gt;
  (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; R) -&amp;gt; (P &amp;lt;-&amp;gt; R).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R [HPQ HQP] [HQR HRQ]. (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P &amp;lt;-&amp;gt; R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                                 (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P -&amp;gt; R *)&lt;br /&gt;
    intros HP.                      (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       HP : P&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       R *)&lt;br /&gt;
    apply HQR.                      (* Q *)&lt;br /&gt;
    apply HPQ.                      (* P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
  -                                 (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       R -&amp;gt; P *)&lt;br /&gt;
    intros HR.                      (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       HR : R&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P *)&lt;br /&gt;
    apply HQP.                      (* Q *)&lt;br /&gt;
    apply HRQ.                      (* R *)&lt;br /&gt;
    apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.6. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        P \/ (Q /\ R) &amp;lt;-&amp;gt; (P \/ Q) /\ (P \/ R).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem distributiva_disy_conj: forall P Q R : Prop,&lt;br /&gt;
  P \/ (Q /\ R) &amp;lt;-&amp;gt; (P \/ Q) /\ (P \/ R).&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                             (* P, Q, R : Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) -&amp;gt; (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
    intros [HP | [HQ HR]].&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ Q *)&lt;br /&gt;
        left.                   (* P *)&lt;br /&gt;
        apply HP.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ R *)&lt;br /&gt;
        left.                   (* P *)&lt;br /&gt;
        apply HP.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ Q *)&lt;br /&gt;
        right.                  (* Q *)&lt;br /&gt;
        apply HQ.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ R *)&lt;br /&gt;
        right.                  (* R *)&lt;br /&gt;
        apply HR.&lt;br /&gt;
  -                             (* P, Q, R : Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) -&amp;gt; P \/ (Q /\ R) *)&lt;br /&gt;
    intros [[HP1|HQ] [HP2|HR]]. &lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP1, HP2 : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP1.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP1 : P&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP1.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HP2 : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP2.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      right.                    (* Q /\ R *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Q *)&lt;br /&gt;
        apply HQ.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   R *)&lt;br /&gt;
        apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Se importa la librería Coq.Setoids.Setoid para usar las&lt;br /&gt;
   tácticas reflexivity y rewrite con iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Require Import Coq.Setoids.Setoid.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.5. Demostrar que&lt;br /&gt;
      forall n m : nat, n * m = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_0 : forall n m : nat, n * m = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                  (* n, m : nat&lt;br /&gt;
                        ============================&lt;br /&gt;
                        n * m = 0 -&amp;gt; n = 0 \/ m = 0 *)&lt;br /&gt;
    apply mult_eq_0. &lt;br /&gt;
  -                  (* n, m : nat&lt;br /&gt;
                        ============================&lt;br /&gt;
                        n = 0 \/ m = 0 -&amp;gt; n * m = 0 *)&lt;br /&gt;
    apply disy_ej.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.6. Demostrar que&lt;br /&gt;
      forall P Q R : Prop, &lt;br /&gt;
        P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma disy_asociativa :&lt;br /&gt;
  forall P Q R : Prop, P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R.           (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                       (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) -&amp;gt; (P \/ Q) \/ R *)&lt;br /&gt;
    intros [H | [H | H]]. &lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P \/ Q *)&lt;br /&gt;
      left.               (* P *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : Q&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P \/ Q *)&lt;br /&gt;
      right.              (* Q *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : R&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      right.              (* R *)&lt;br /&gt;
      apply H.&lt;br /&gt;
  -                       (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R -&amp;gt; P \/ (Q \/ R) *)&lt;br /&gt;
    intros [[H | H] | H].&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : Q&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) *)&lt;br /&gt;
      right.              (* Q \/ R *)&lt;br /&gt;
      left.               (* Q *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : R&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) *)&lt;br /&gt;
      right.              (* Q \/ R *)&lt;br /&gt;
      right.              (* R *)&lt;br /&gt;
      apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.7. Demostrar que&lt;br /&gt;
      forall n m p : nat,&lt;br /&gt;
        n * m * p = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0 \/ p = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_0_3: forall n m p : nat,&lt;br /&gt;
    n * m * p = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0 \/ p = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.            (* n, m, p : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * (m * p) = 0 &amp;lt;-&amp;gt; n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite mult_0.          (* n * m = 0 \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite mult_0.          (* (n = 0 \/ m = 0) \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite disy_asociativa. (* (n = 0 \/ m = 0) \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              (n = 0 \/ m = 0) \/ p = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de reflexivity y rewrite con iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.8. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_apply_iff: forall n m : nat,&lt;br /&gt;
    n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : n * m = 0&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = 0 \/ m = 0 *)&lt;br /&gt;
  apply mult_0. (* n * m = 0 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de apply sobre iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.6. Cuantificación existencial  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.1. Demostrar que&lt;br /&gt;
      exists n : nat, 4 = n + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuatro_es_par: exists n : nat, 4 = n + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  exists 2.          (* &lt;br /&gt;
                   ============================&lt;br /&gt;
                   4 = 2 + 2 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;exists a&amp;#039; sustituye el objetivo de la forma &lt;br /&gt;
   (exists x, P(x)) por P(a).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(** Conversely, if we have an existential hypothesis [exists x, P] in&lt;br /&gt;
    the context, we can destruct it to obtain a witness [x] and a&lt;br /&gt;
    hypothesis stating that [P] holds of [x]. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.2. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        (exists m, n = 4 + m) -&amp;gt; (exists o, n = 2 + o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem ej_existe_2a: forall n : nat,&lt;br /&gt;
  (exists m, n = 4 + m) -&amp;gt;&lt;br /&gt;
  (exists o, n = 2 + o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.&lt;br /&gt;
  destruct H as [a Ha].&lt;br /&gt;
  exists (2 + a).&lt;br /&gt;
  apply Ha.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem ej_existe_2b: forall n : nat,&lt;br /&gt;
  (exists m, n = 4 + m) -&amp;gt;&lt;br /&gt;
  (exists o, n = 2 + o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n [a Ha]. &lt;br /&gt;
  exists (2 + a).&lt;br /&gt;
  apply Ha.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. &amp;#039;destruct H [a Ha]&amp;#039; sustituye la hipótesis (H : exists x, P(x)) &lt;br /&gt;
      por (Ha : P(a)).&lt;br /&gt;
   2. &amp;#039;intros x [a Ha]&amp;#039; sustituye el objetivo &lt;br /&gt;
      (forall x, (exists y P(y)) -&amp;gt; Q(x)) por Q(x) y le añade la&lt;br /&gt;
      hipótesis (Ha : P(a)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.1. Demostrar que&lt;br /&gt;
      forall (X:Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
        (forall x, P x) -&amp;gt; ~ (exists x, ~ P x)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem paraTodo_no_existe_no: forall (X:Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
  (forall x, P x) -&amp;gt; ~ (exists x, ~ P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X P H1 [a Ha]. (* X : Type&lt;br /&gt;
                           P : X -&amp;gt; Prop&lt;br /&gt;
                           H1 : forall x : X, P x&lt;br /&gt;
                           a : X&lt;br /&gt;
                           Ha : ~ P a&lt;br /&gt;
                           ============================&lt;br /&gt;
                           False *)&lt;br /&gt;
  apply Ha.             (* P a *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (P Q : X -&amp;gt; Prop),&lt;br /&gt;
        (exists x, P x \/ Q x) &amp;lt;-&amp;gt; (exists x, P x) \/ (exists x, Q x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem dist_existe: forall (X : Type) (P Q : X -&amp;gt; Prop),&lt;br /&gt;
  (exists x, P x \/ Q x) &amp;lt;-&amp;gt; (exists x, P x) \/ (exists x, Q x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X P Q.                 (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x \/ Q x) &amp;lt;-&amp;gt; &lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x : X, P x \/ Q x) -&amp;gt; &lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
    intros [a [HPa | HQa]].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HPa : P a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
      left.                     (* exists x : X, P x *)&lt;br /&gt;
      exists a.                      (* P a *)&lt;br /&gt;
      apply HPa.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HQa : Q a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
      right.                    (* exists x : X, Q x *)&lt;br /&gt;
      exists a.                      (* Q a *)&lt;br /&gt;
      apply HQa.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) -&amp;gt; &lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
    intros [[a HPa] | [a HQa]]. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HPa : P a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
      exists a.                      (* P a \/ Q a *)&lt;br /&gt;
      left.                     (* P a *)&lt;br /&gt;
      apply HPa.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HQa : Q a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
      exists a.                      (* P a \/ Q a *)&lt;br /&gt;
      right.                    (* Q a *)&lt;br /&gt;
      apply HQa.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Programación con proposiciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.1. Definir la función&lt;br /&gt;
      En {A : Type} (x : A) (xs : list A) : Prop :=&lt;br /&gt;
   tal que (En x xs) se verifica si x pertenece a xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint En {A : Type} (x : A) (xs : list A) : Prop :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []        =&amp;gt; False&lt;br /&gt;
  | x&amp;#039; :: xs&amp;#039; =&amp;gt; x&amp;#039; = x \/ En x xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.2. Demostrar que&lt;br /&gt;
      En 4 [1; 2; 3; 4; 5].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example En_ejemplo_1 : En 4 [1; 2; 3; 4; 5].&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* 1 = 4 \/ 2 = 4 \/ 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 2 = 4 \/ 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  left.        (* 4 = 4 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.3. Demostrar que&lt;br /&gt;
      forall n : nat, &lt;br /&gt;
        En n [2; 4] -&amp;gt; exists n&amp;#039;, n = 2 * n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example En_ejemplo_2: forall n : nat,&lt;br /&gt;
    En n [2; 4] -&amp;gt; exists n&amp;#039;, n = 2 * n&amp;#039;.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.                   (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              forall n : nat,&lt;br /&gt;
                               2 = n \/ 4 = n \/ False -&amp;gt; &lt;br /&gt;
                               exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
  intros n [H | [H | []]]. &lt;br /&gt;
  -                        (* n : nat&lt;br /&gt;
                              H : 2 = n&lt;br /&gt;
                              ============================&lt;br /&gt;
                              exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
    exists 1.                   (* n = 1 + (1 + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- H.           (* 2 = 1 + (1 + 0) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* n : nat&lt;br /&gt;
                              H : 4 = n&lt;br /&gt;
                              ============================&lt;br /&gt;
                              exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
    exists 2.                   (* n = 2 + (2 + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- H.           (* 4 = 2 + (2 + 0) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso del patrón vacóp para descartar el último caso.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (x : A),&lt;br /&gt;
        En x xs -&amp;gt;&lt;br /&gt;
        En (f x) (map f xs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lemma En_map: forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (x : A),&lt;br /&gt;
    En x xs -&amp;gt;&lt;br /&gt;
    En (f x) (map f xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f xs x.            (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   xs : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x xs -&amp;gt; En (f x) (map f xs) *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x [ ] -&amp;gt; En (f x) (map f [ ]) *)&lt;br /&gt;
    simpl.                      (* False -&amp;gt; False *)&lt;br /&gt;
    intros [].&lt;br /&gt;
  -                             (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x (x&amp;#039;::xs&amp;#039;) -&amp;gt; &lt;br /&gt;
                                   En (f x) (map f (x&amp;#039;::xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                      (* x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
    intros [H | H].&lt;br /&gt;
    +                           (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   H : x&amp;#039; = x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      rewrite H.                (* f x = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      left.                     (* f x = f x *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   H : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      right.                    (* En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      apply HI.                 (* En x xs&amp;#039; *)&lt;br /&gt;
      apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (y : B),&lt;br /&gt;
        En y (map f xs) &amp;lt;-&amp;gt;&lt;br /&gt;
        exists x, f x = y /\ En x xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma En_map_iff: forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (y : B),&lt;br /&gt;
    En y (map f xs) &amp;lt;-&amp;gt;&lt;br /&gt;
    exists x, f x = y /\ En x xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f xs y.                  (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         xs : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f xs) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x xs) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                                   (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f [ ]) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x [ ]) *)&lt;br /&gt;
    simpl.                            (* En y (map f [ ]) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x [ ]) *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         False -&amp;gt; &lt;br /&gt;
                                         exists x : A, f x = y /\ False *)&lt;br /&gt;
      intros [].&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         (exists x : A, f x = y /\ False) -&amp;gt; &lt;br /&gt;
                                         False *)&lt;br /&gt;
      intros [a [H []]].&lt;br /&gt;
  -                                   (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f (x :: xs&amp;#039;)) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                           f x0 = y /\ En x0 (x :: xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                            (* f x = y \/ En y (map f xs&amp;#039;) &amp;lt;-&amp;gt;&lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                           f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;)) *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) -&amp;gt;&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
      intros [H1 | H2].&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        exists x.                        (* f x = y /\ (x = x \/ En x xs&amp;#039;) *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y *)&lt;br /&gt;
          apply H1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         x = x \/ En x xs&amp;#039; *)&lt;br /&gt;
          left.                       (* x = x *)&lt;br /&gt;
          reflexivity.&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H2 : En y (map f xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        apply HI in H2.               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H2 : exists x : A, f x = y /\ En x xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        destruct H2 as [a [Ha1 Ha2]]. (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        &lt;br /&gt;
        exists a.                          (* En y (map f xs) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x xs) *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f a = y *)&lt;br /&gt;
          apply Ha1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         x = a \/ En a xs&amp;#039; *)&lt;br /&gt;
          right.                      (* En a xs&amp;#039; *)&lt;br /&gt;
          apply Ha2.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x : A, &lt;br /&gt;
                                                f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;)) -&amp;gt;&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
      intros [a [Ha1 [Ha2 | Ha3]]].&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : x = a&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
        left.                         (* f x = y *)&lt;br /&gt;
        rewrite Ha2.                  (* f a = y *)&lt;br /&gt;
        rewrite Ha1.                  (* y = y *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
        right.                        (* En y (map f xs&amp;#039;) *)&lt;br /&gt;
        apply HI.                     (* exists x0 : A, f x0 = y /\ En x0 xs&amp;#039; *)&lt;br /&gt;
        exists a.                          (* f a = y /\ En a xs&amp;#039; *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f a = y *)&lt;br /&gt;
          apply Ha1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En a xs&amp;#039; *)&lt;br /&gt;
          apply Ha3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall A (xs ys : list A) (a : A),&lt;br /&gt;
        En a (xs ++ ys) &amp;lt;-&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma En_conc_1: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a (xs ++ ys) -&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].    &lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a ([ ] ++ ys) -&amp;gt; En a [ ] \/ En a ys *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a ys -&amp;gt; False \/ En a ys *)&lt;br /&gt;
    intros ys a H.                (* A : Type&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     False \/ En a ys *)&lt;br /&gt;
    right.                        (* En a ys *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A),&lt;br /&gt;
                                      En a ((x :: xs&amp;#039;) ++ ys) -&amp;gt; &lt;br /&gt;
                                      En a (x :: xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A),&lt;br /&gt;
                                      x = a \/ En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                      (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
    intros ys a [H1 | H2].&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H1 : x = a&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
      left.                       (* x = a \/ En a xs&amp;#039; *)&lt;br /&gt;
      left.                       (* x = a *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H2 : En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
      rewrite &amp;lt;- disy_asociativa.  (* x = a \/ (En a xs&amp;#039; \/ En a ys) *)&lt;br /&gt;
      right.                      (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      apply HI.                   (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma En_conc_2: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a xs \/ En a ys -&amp;gt; En a (xs ++ ys). &lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a [ ] \/ En a ys -&amp;gt; En a ([ ] ++ ys) *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A), &lt;br /&gt;
                                      False \/ En a ys -&amp;gt; En a ys *)&lt;br /&gt;
    intros ys a [[] | H].         (* A : Type&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a ys *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A),&lt;br /&gt;
                                      En a (x :: xs&amp;#039;) \/ En a ys -&amp;gt; &lt;br /&gt;
                                      En a ((x :: xs&amp;#039;) ++ ys) *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A),&lt;br /&gt;
                                      (x = a \/ En a xs&amp;#039;) \/ En a ys -&amp;gt; &lt;br /&gt;
                                      x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
    intros ys a [[H1 | H2] | H3]. &lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H1 : x = a&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      left.                       (* x = a *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H2 : En a xs&amp;#039;&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      right.                      (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply HI.                   (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      left.                       (* En a xs&amp;#039; *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H3 : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      right.                      (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply HI.                   (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      right.                      (* En a ys *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
Lemma En_conc: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a (xs ++ ys) &amp;lt;-&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                  (* A : Type&lt;br /&gt;
                        xs, ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a (xs ++ ys) -&amp;gt; En a xs \/ En a ys *)&lt;br /&gt;
    apply En_conc_1. &lt;br /&gt;
  -                  (* A : Type&lt;br /&gt;
                                     xs, ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a xs \/ En a ys -&amp;gt; En a (xs ++ ys) *)&lt;br /&gt;
    apply En_conc_2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3.1. Definir la propiedad&lt;br /&gt;
      Todos {T : Type} (P : T -&amp;gt; Prop) (xs : list T) : Prop&lt;br /&gt;
   tal que (Todos P xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   la propiedad P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint Todos {T : Type} (P : T -&amp;gt; Prop) (xs : list T) : Prop :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; True&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; P x /\ Todos P xs&amp;#039; &lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3.2. Demostrar que&lt;br /&gt;
      forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
        (forall x, En x xs -&amp;gt; P x) &amp;lt;-&amp;gt;&lt;br /&gt;
        Todos P xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En_1: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x) -&amp;gt;&lt;br /&gt;
    Todos P xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].  &lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (forall x : T, En x [ ] -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                   Todos P [ ] *) &lt;br /&gt;
    simpl.                      (* (forall x : T, False -&amp;gt; P x) -&amp;gt; True *)&lt;br /&gt;
    intros.                     (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   H : forall x : T, False -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   True *)&lt;br /&gt;
    apply I.&lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (forall x : T, En x (x&amp;#039; :: xs&amp;#039;) -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                   Todos P (x&amp;#039; :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* (forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x) -&amp;gt;&lt;br /&gt;
                                   P x&amp;#039; /\ Todos P xs&amp;#039; *)&lt;br /&gt;
    intros H.                   (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x&amp;#039; /\ Todos P xs&amp;#039; *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x&amp;#039; *)&lt;br /&gt;
      apply H.                  (* x&amp;#039; = x&amp;#039; \/ En x&amp;#039; xs&amp;#039; *)&lt;br /&gt;
      left.                     (* x&amp;#039; = x&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P xs&amp;#039; *)&lt;br /&gt;
      apply HI.                 (* forall x : T, En x xs&amp;#039; -&amp;gt; P x *)&lt;br /&gt;
      intros x H1.              (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H1 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      apply H.                  (* x&amp;#039; = x \/ En x xs&amp;#039; *)&lt;br /&gt;
      right.                    (* En x xs&amp;#039; *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En_2: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    Todos P xs -&amp;gt;&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P [ ] -&amp;gt; &lt;br /&gt;
                                   forall x : T, En x [ ] -&amp;gt; P x *)&lt;br /&gt;
    simpl.                      (* True -&amp;gt; forall x : T, False -&amp;gt; P x *)&lt;br /&gt;
    intros [].                  (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall x : T, False -&amp;gt; P x *)&lt;br /&gt;
    intros x [].&lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P (x&amp;#039; :: xs&amp;#039;) -&amp;gt; &lt;br /&gt;
                                   forall x : T, En x (x&amp;#039; :: xs&amp;#039;) -&amp;gt; P x *)&lt;br /&gt;
    simpl.                      (* P x&amp;#039; /\ Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                   forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x *)&lt;br /&gt;
    intros [H1 H2] x [H3 | H4]. &lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H3 : x&amp;#039; = x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      rewrite &amp;lt;- H3.             (* P x&amp;#039; *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
      *                         (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P xs&amp;#039; *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
      *                         (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x xs&amp;#039; *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x) &amp;lt;-&amp;gt;&lt;br /&gt;
    Todos P xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                   (* T : Type&lt;br /&gt;
                         P : T -&amp;gt; Prop&lt;br /&gt;
                         xs : list T&lt;br /&gt;
                         ============================&lt;br /&gt;
                         (forall x : T, En x xs -&amp;gt; P x) -&amp;gt; Todos P xs *)&lt;br /&gt;
    apply Todos_En_1. &lt;br /&gt;
  -                   (* T : Type&lt;br /&gt;
                         P : T -&amp;gt; Prop&lt;br /&gt;
                         xs : list T&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Todos P xs -&amp;gt; forall x : T, En x xs -&amp;gt; P x *)&lt;br /&gt;
    apply Todos_En_2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.1. Definir la propiedad&lt;br /&gt;
      combina_par_impar (Pimpar Ppar : nat -&amp;gt; Prop) : nat -&amp;gt; Prop&lt;br /&gt;
   tal que (combina_par_impar Pimpar Ppar) es una función que asigna a n&lt;br /&gt;
   (Pimpar n) si n es impar y (Ppar n) si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition combina_par_impar (Pimpar Ppar : nat -&amp;gt; Prop) : nat -&amp;gt; Prop :=&lt;br /&gt;
  fun n =&amp;gt; (esImpar n = true -&amp;gt; Pimpar n) /\&lt;br /&gt;
        (esImpar n = false -&amp;gt; Ppar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.2. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        (esImpar n = true -&amp;gt; Pimpar n) -&amp;gt;&lt;br /&gt;
        (esImpar n = false -&amp;gt; Ppar n) -&amp;gt;&lt;br /&gt;
        combina_par_impar Pimpar Ppar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_intro :&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    (esImpar n = true -&amp;gt; Pimpar n) -&amp;gt;&lt;br /&gt;
    (esImpar n = false -&amp;gt; Ppar n) -&amp;gt;&lt;br /&gt;
    combina_par_impar Pimpar Ppar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Par n H1 H2. (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                combina_par_impar Pimpar Par n *)&lt;br /&gt;
  unfold combina_par_impar.  (* (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                (esImpar n = false -&amp;gt; Par n) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                          (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                esImpar n = true -&amp;gt; Pimpar n *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                esImpar n = false -&amp;gt; Par n *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.3. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
        esImpar n = true -&amp;gt;&lt;br /&gt;
        Pimpar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_elim_impar:&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
    esImpar n = true -&amp;gt;&lt;br /&gt;
    Pimpar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Ppar n H1 H2.     (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : combina_par_impar Pimpar Ppar n&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                    Pimpar n *)&lt;br /&gt;
  unfold combina_par_impar in H1. (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                          (esImpar n = false -&amp;gt; Ppar n)&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Pimpar n *)&lt;br /&gt;
  destruct H1 as [H3 H4].         (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H3 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                     H4 : esImpar n = false -&amp;gt; Ppar n&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Pimpar n *)&lt;br /&gt;
  apply H3.                       (* esImpar n = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.4. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
        esImpar n = false -&amp;gt;&lt;br /&gt;
        Ppar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_elim_par:&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
    esImpar n = false -&amp;gt;&lt;br /&gt;
    Ppar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Ppar n H1 H2.     (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : combina_par_impar Pimpar Ppar n&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  unfold combina_par_impar in H1. (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                          (esImpar n = false -&amp;gt; Ppar n)&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  destruct H1 as [H3 H4].         (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H3 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                     H4 : esImpar n = false -&amp;gt; Ppar n&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  apply H4.                       (* esImpar n = false *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Aplicando teoremas a argumentos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Evaluar la expresión&lt;br /&gt;
      Check suma_conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check suma_conmutativa.&lt;br /&gt;
(* ===&amp;gt; forall n m : nat, n + m = m + n *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En Coq, las demostraciones son objetos de primera clase.&lt;br /&gt;
   2. Coq devuelve el tipo de suma_conmutativa como es de cualquier&lt;br /&gt;
      expresión.&lt;br /&gt;
   3. El identificador suma_conmutativa representa un objeto prueba de&lt;br /&gt;
      (forall n m : nat, n + m = m + n).&lt;br /&gt;
   4. Un término de tipo (nat -&amp;gt; nat -&amp;gt; nat) transforma dos naturales en&lt;br /&gt;
      un natural.&lt;br /&gt;
   5. Análogamente, un término de tipo (n = m -&amp;gt; n + n = m + m)&lt;br /&gt;
      transforma un argumento de tipo (n = m) en otro de tipo &lt;br /&gt;
      (n + n = m + m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Operationally, this analogy goes even further: by applying a&lt;br /&gt;
    theorem, as if it were a function, to hypotheses with matching&lt;br /&gt;
    types, we can specialize its result without having to resort to&lt;br /&gt;
    intermediate assertions.  For example, suppose we wanted to prove&lt;br /&gt;
    the following result: *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.2. Demostrar que&lt;br /&gt;
      forall x y z : nat, &lt;br /&gt;
        x + (y + z) = (z + y) + x.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Lemma suma_conmutativa3a :&lt;br /&gt;
  forall x y z : nat,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.             (* x, y, z : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               x + (y + z) = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa. (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa. (* x + (y + z) = (z + y) + x *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Lemma suma_conmutativa3b :&lt;br /&gt;
  forall x y z,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.               (* x, y, z : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x + (y + z) = z + y + x *)&lt;br /&gt;
  rewrite suma_conmutativa.   (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  assert (H : y + z = z + y). &lt;br /&gt;
  -                           (* x, y, z : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 y + z = z + y *)&lt;br /&gt;
    rewrite suma_conmutativa. (* z + y = z + y *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* x, y, z : nat&lt;br /&gt;
                                 H : y + z = z + y&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (y + z) + x = (z + y) + x *)&lt;br /&gt;
    rewrite H.                (* (z + y) + x = (z + y) + x *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 3º intento *)&lt;br /&gt;
Lemma suma_conmutativa3c:&lt;br /&gt;
  forall x y z,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.                   (* x, y, z : nat&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x + (y + z) = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa.       (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  rewrite (suma_conmutativa y z). (* (z + y) + x = (z + y) + x *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Indicación en (rewrite (suma_conmutativa y z)) de los&lt;br /&gt;
   argumentos con los que se aplica, análogamente a las funciones&lt;br /&gt;
   polimórficas. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.3. Demostrar que&lt;br /&gt;
     forall {n : nat} {ns : list nat},&lt;br /&gt;
       En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
       n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Lema auxiliar *)&lt;br /&gt;
Lemma producto_n_0:&lt;br /&gt;
  forall n : nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              0 * 0 = 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                        (* n&amp;#039; : nat&lt;br /&gt;
                              HI : n&amp;#039; * 0 = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              S n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    simpl.                 (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ej_aplicacion_de_lema_1:&lt;br /&gt;
  forall {n : nat} {ns : list nat},&lt;br /&gt;
    En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
    n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n ns H.              (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  rewrite En_map_iff in H.    (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 H : exists x : nat, x * 0 = n /\ En x ns&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  destruct H as [m [Hm _]].   (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 m : nat&lt;br /&gt;
                                 Hm : m * 0 = n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  rewrite producto_n_0 in Hm. (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 m : nat&lt;br /&gt;
                                 Hm : 0 = n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  symmetry.                   (* 0 = n *)&lt;br /&gt;
  apply Hm.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ej_aplicacion_de_lema:&lt;br /&gt;
  forall {n : nat} {ns : list nat},&lt;br /&gt;
    En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
    n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n ns H.                    (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  destruct (conj_e1 _ _&lt;br /&gt;
             (En_map_iff _ _ _ _ _) &lt;br /&gt;
             H)&lt;br /&gt;
           as [m [Hm _]].           (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       m : nat&lt;br /&gt;
                                       Hm : m * 0 = n&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  rewrite producto_n_0 in Hm.       (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       m : nat&lt;br /&gt;
                                       Hm : 0 = n&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  symmetry.                         (* 0 = n *)&lt;br /&gt;
  apply Hm.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Aplicación de teoremas a argumentos con&lt;br /&gt;
      (conj_e1 _ _  (En_map_iff _ _ _ _ _) H)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Coq vs. teoría de conjuntos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En lugar de decir que un elemento pertenece a un conjunto se puede&lt;br /&gt;
      decir que verifica la propiedad que define al conjunto.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.1. Extensionalidad funcional&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.1. Demostrar que&lt;br /&gt;
      plus 3 = plus (pred 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example igualdad_de_funciones_ej1:&lt;br /&gt;
  suma 3 = suma (pred 4).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.2. Definir el axioma de extensionalidad funcional que&lt;br /&gt;
   afirma que dos funciones son giuales cuando tienen los mismos&lt;br /&gt;
   valores. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Axiom extensionalidad_funcional : forall {X Y: Type}&lt;br /&gt;
                                    {f g : X -&amp;gt; Y},&lt;br /&gt;
  (forall (x:X), f x = g x) -&amp;gt; f = g.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.3. Demostrar que&lt;br /&gt;
      (fun x =&amp;gt; suma x 1) = (fun x =&amp;gt; suma 1 x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example igualdad_de_funciones_ej2 :&lt;br /&gt;
  (fun x =&amp;gt; suma x 1) = (fun x =&amp;gt; suma 1 x).&lt;br /&gt;
Proof.&lt;br /&gt;
  apply extensionalidad_funcional. (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      forall x : nat, suma x 1 = suma 1 x *)&lt;br /&gt;
  intros x.                        (* x : nat&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      suma x 1 = suma 1 x *)&lt;br /&gt;
  apply suma_conmutativa.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. No se puede demostrar sin el axioma.&lt;br /&gt;
   2. Hay que ser cuidadoso en la definición de axiomas, porque se&lt;br /&gt;
      pueden introducir inconsistencias. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.4. Calcular los axiomas usados en la prueba de &lt;br /&gt;
      igualdad_de_funciones_ej2&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Print Assumptions igualdad_de_funciones_ej2.&lt;br /&gt;
(* ===&amp;gt;&lt;br /&gt;
     Axioms:&lt;br /&gt;
     extensionalidad_funcional :&lt;br /&gt;
         forall (X Y : Type) (f g : X -&amp;gt; Y),&lt;br /&gt;
                (forall x : X, f x = g x) -&amp;gt; f = g *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1.1. Se considera la siguiente definición iterativa de la&lt;br /&gt;
   función inversa&lt;br /&gt;
      Fixpoint inversaIaux {X} (xs ys : list X) : list X :=&lt;br /&gt;
        match xs with&lt;br /&gt;
        | []       =&amp;gt; ys&lt;br /&gt;
        | x :: xs&amp;#039; =&amp;gt; inversaIaux xs&amp;#039; (x :: ys)&lt;br /&gt;
        end.&lt;br /&gt;
      &lt;br /&gt;
      Definition inversaI {X} (xs : list X) : list X :=&lt;br /&gt;
        inversaIaux xs [].&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall X : Type, &lt;br /&gt;
        @inversaI X = @inversa X.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint inversaIaux {X} (xs ys : list X) : list X :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []       =&amp;gt; ys&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; inversaIaux xs&amp;#039; (x :: ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Definition inversaI {X} (xs : list X) : list X :=&lt;br /&gt;
  inversaIaux xs [].&lt;br /&gt;
&lt;br /&gt;
Lemma inversaI_correcta_aux:&lt;br /&gt;
  forall (X : Type) (xs ys : list X),&lt;br /&gt;
    inversaIaux xs ys = inversa xs ++ ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux xs ys = inversa xs ++ ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].  &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux [ ] ys = inversa [ ] ++ ys *)&lt;br /&gt;
    simpl.                      (* forall ys : list X, ys = ys *)&lt;br /&gt;
    intros.                     (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   ys = ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : forall ys : list X, &lt;br /&gt;
                                         inversaIaux xs&amp;#039; ys = inversa xs&amp;#039; ++ ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux (x :: xs&amp;#039;) ys = &lt;br /&gt;
                                    inversa (x :: xs&amp;#039;) ++ ys *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : forall ys : list X, &lt;br /&gt;
                                         inversaIaux xs&amp;#039; ys = inversa xs&amp;#039; ++ ys&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   inversaIaux (x :: xs&amp;#039;) ys = &lt;br /&gt;
                                   inversa (x :: xs&amp;#039;) ++ ys *)&lt;br /&gt;
    simpl.                      (* inversaIaux xs&amp;#039; (x :: ys) = &lt;br /&gt;
                                   (inversa xs&amp;#039; ++ [x]) ++ ys *)&lt;br /&gt;
    rewrite &amp;lt;- conc_asociativa.  (* inversaIaux xs&amp;#039; (x :: ys) = &lt;br /&gt;
                                   inversa xs&amp;#039; ++ ([x] ++ ys) *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
                                            &lt;br /&gt;
Lemma inversaI_correcta:&lt;br /&gt;
  forall X : Type,&lt;br /&gt;
    @inversaI X = @inversa X.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X.                        (* X : Type&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      inversaI = inversa *)&lt;br /&gt;
  apply extensionalidad_funcional. (* forall x : list X, &lt;br /&gt;
                                       inversaI x = inversa x *)&lt;br /&gt;
  intros.                          (* X : Type&lt;br /&gt;
                                      x : list X&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      inversaI x = inversa x *)&lt;br /&gt;
  unfold inversaI.                 (* inversaIaux x [ ] = inversa x *)&lt;br /&gt;
  rewrite inversaI_correcta_aux.   (* inversa x ++ [ ] = inversa x *)&lt;br /&gt;
  apply conc_nil.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.2. Proposiciones y booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.1. Demostrar que&lt;br /&gt;
     forall k : nat,&lt;br /&gt;
       esPar (doble k) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_doble:&lt;br /&gt;
  forall k : nat,&lt;br /&gt;
    esPar (doble k) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros k.                (* k : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble k) = true *)&lt;br /&gt;
  induction k as [|k&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble 0) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* k&amp;#039; : nat&lt;br /&gt;
                              HI : esPar (doble k&amp;#039;) = true&lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble (S k&amp;#039;)) = true *)&lt;br /&gt;
    simpl.                 (* esPar (doble k&amp;#039;) = true *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.1. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        exists k : nat, n = if esPar n&lt;br /&gt;
                     then doble k&lt;br /&gt;
                     else S (doble k).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_doble_aux :&lt;br /&gt;
  forall n : nat,&lt;br /&gt;
    exists k : nat, n = if esPar n&lt;br /&gt;
                 then doble k&lt;br /&gt;
                 else S (doble k).&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HI].    &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   0 = (if esPar 0 &lt;br /&gt;
                                        then doble k &lt;br /&gt;
                                        else S (doble k)) *)&lt;br /&gt;
    exists 0.                       (* 0 = (if esPar 0 &lt;br /&gt;
                                       then doble 0 &lt;br /&gt;
                                       else S (doble 0)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* n&amp;#039; : nat&lt;br /&gt;
                                  HI : exists k : nat, &lt;br /&gt;
                                        n&amp;#039; = (if esPar n&amp;#039; &lt;br /&gt;
                                              then doble k &lt;br /&gt;
                                              else S (doble k))&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
    destruct (esPar n&amp;#039;) eqn:H. &lt;br /&gt;
    +                          (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = true&lt;br /&gt;
                                  HI : exists k : nat, n&amp;#039; = doble k&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite esPar_S.         (* exists k : nat,&lt;br /&gt;
                                   S n&amp;#039; = (if negacion (esPar n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite H.               (* exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if negacion true &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      simpl.                   (* exists k : nat, S n&amp;#039; = S (doble k) *)&lt;br /&gt;
      destruct HI as [k&amp;#039; Hk&amp;#039;]. (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = true&lt;br /&gt;
                                  k&amp;#039; : nat&lt;br /&gt;
                                  Hk&amp;#039; : n&amp;#039; = doble k&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, S n&amp;#039; = S (doble k) *)&lt;br /&gt;
      exists k&amp;#039;.                    (* S n&amp;#039; = S (doble k&amp;#039;) *)&lt;br /&gt;
      rewrite Hk&amp;#039;.             (* S (doble k&amp;#039;) = S (doble k&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = false&lt;br /&gt;
                                  HI : exists k : nat, n&amp;#039; = S (doble k)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite esPar_S.         (* exists k : nat,&lt;br /&gt;
                                   S n&amp;#039; = (if negacion (esPar n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite H.               (* exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if negacion false &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      simpl.                   (* exists k : nat, S n&amp;#039; = doble k *)&lt;br /&gt;
      destruct HI as [k&amp;#039; Hk&amp;#039;]. (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = false&lt;br /&gt;
                                  k&amp;#039; : nat&lt;br /&gt;
                                  Hk&amp;#039; : n&amp;#039; = S (doble k&amp;#039;)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, S n&amp;#039; = doble k *)&lt;br /&gt;
      exists (1 + k&amp;#039;).              (* S n&amp;#039; = doble (1 + k&amp;#039;) *)&lt;br /&gt;
      rewrite Hk&amp;#039;.             (* S (S (doble k&amp;#039;)) = doble (1 + k&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.2. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        esPar n = true &amp;lt;-&amp;gt; exists k, n = doble k.&lt;br /&gt;
&lt;br /&gt;
   Es decir, que la computación booleana (esPar n) refleja la&lt;br /&gt;
   proposición (exists k, n = doble k).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_bool_prop:&lt;br /&gt;
  forall n : nat,&lt;br /&gt;
    esPar n = true &amp;lt;-&amp;gt; exists k, n = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true &amp;lt;-&amp;gt; (exists k : nat, n = doble k) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                       (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true -&amp;gt; exists k : nat, n = doble k *)&lt;br /&gt;
    intros H.             (* n : nat                           &lt;br /&gt;
                             H : esPar n = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             exists k : nat, n = doble k *)&lt;br /&gt;
    destruct&lt;br /&gt;
      (esPar_doble_aux n) &lt;br /&gt;
      as [k Hk].          (* n : nat&lt;br /&gt;
                             H : esPar n = true&lt;br /&gt;
                             k : nat&lt;br /&gt;
                             Hk : n = (if esPar n then doble k else S (doble k))&lt;br /&gt;
                             ============================&lt;br /&gt;
                             exists k0 : nat, n = doble k0 *)&lt;br /&gt;
    rewrite Hk.           (* exists k0 : nat, &lt;br /&gt;
                              (if esPar n &lt;br /&gt;
                               then doble k &lt;br /&gt;
                               else S (doble k)) &lt;br /&gt;
                              = doble k0 *)&lt;br /&gt;
    rewrite H.            (* exists k0 : nat, doble k = doble k0 *)&lt;br /&gt;
    exists k.                  (* doble k = doble k *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                       (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (exists k : nat, n = doble k) -&amp;gt; esPar n = true *)&lt;br /&gt;
    intros [k Hk].        (* n, k : nat&lt;br /&gt;
                             Hk : n = doble k&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true *)&lt;br /&gt;
    rewrite Hk.           (* esPar (doble k) = true *)&lt;br /&gt;
    apply esPar_doble.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.3. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true &amp;lt;-&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_bool_prop:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true &amp;lt;-&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true &amp;lt;-&amp;gt; n = m *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                           (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true -&amp;gt; n = m *)&lt;br /&gt;
    apply iguales_nat_true.&lt;br /&gt;
  -                           (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = m -&amp;gt; iguales_nat n m = true *)&lt;br /&gt;
    intros H.                 (* n, m : nat&lt;br /&gt;
                                 H : n = m&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true *)&lt;br /&gt;
    rewrite H.                (* iguales_nat m m = true *)&lt;br /&gt;
    rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.4. Definir la función es_primo_par tal que &lt;br /&gt;
   (es_primo_par n) es verifica si n es un primo par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fail Definition es_primo_par n :=&lt;br /&gt;
  if n = 2&lt;br /&gt;
  then true&lt;br /&gt;
  else false.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Definition es_primo_par n :=&lt;br /&gt;
  if iguales_nat n 2&lt;br /&gt;
  then true&lt;br /&gt;
  else false.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.1. Demostrar que&lt;br /&gt;
      exists k : nat, 1000 = doble k.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000: exists k : nat, 1000 = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  exists 500.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.2. Demostrar que&lt;br /&gt;
      esPar 1000 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000&amp;#039; : esPar 1000 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.3. Demostrar que&lt;br /&gt;
      exists k : nat, 1000 = doble k.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000&amp;#039;&amp;#039;: exists k : nat, 1000 = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply esPar_bool_prop. (* esPar 1000 = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas. &lt;br /&gt;
   1. En la proposicional se necesita proporcionar un testipo.&lt;br /&gt;
   2. En la booleano se calcula sin testigo.&lt;br /&gt;
   3, Se puede demostrar la proposional usando la equivalencia con la&lt;br /&gt;
      booleana sin necesidad de testigo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.2.1. Demostrar que&lt;br /&gt;
      forall x y : bool,&lt;br /&gt;
        x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_verdad_syss:&lt;br /&gt;
  forall x y : bool,&lt;br /&gt;
    x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.             (* x, y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true *)&lt;br /&gt;
  destruct x.             &lt;br /&gt;
  -                       (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; true = true /\ y = true *)&lt;br /&gt;
    destruct y.           &lt;br /&gt;
    +                     (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; true = true &amp;lt;-&amp;gt; true = true /\ true=true *)&lt;br /&gt;
      simpl.              (* true = true &amp;lt;-&amp;gt; true = true /\ true = true *)&lt;br /&gt;
      split.              &lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true -&amp;gt; true = true /\ true = true *)&lt;br /&gt;
        apply conj_intro. (* true = true *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ true = true -&amp;gt; true = true *)&lt;br /&gt;
        apply conj_e1.&lt;br /&gt;
    +                     (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; false = true &amp;lt;-&amp;gt; true=true /\ false=true *)&lt;br /&gt;
      simpl.              (* false = true &amp;lt;-&amp;gt; true = true /\ false = true *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true -&amp;gt; true = true /\ false = true *)&lt;br /&gt;
        intros H.         (* H : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ false = true *)&lt;br /&gt;
        inversion H.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ false = true -&amp;gt; false = true *)&lt;br /&gt;
        intros [H1 H2].   (* H1 : true = true&lt;br /&gt;
                             H2 : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                       (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; false = true /\ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                     (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false &amp;amp;&amp;amp; y = true -&amp;gt; false = true /\ y = true *)&lt;br /&gt;
      simpl.              (* false = true -&amp;gt; false = true /\ y = true *)&lt;br /&gt;
      intros H.           (* y : bool&lt;br /&gt;
                             H : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true /\ y = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true /\ y = true -&amp;gt; false &amp;amp;&amp;amp; y = true *)&lt;br /&gt;
      simpl.              (* false = true /\ y = true -&amp;gt; false = true *)&lt;br /&gt;
      intros [H1 H2].     (* y : bool&lt;br /&gt;
                             H1 : false = true&lt;br /&gt;
                             H2 : y = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.2.2. Demostrar que&lt;br /&gt;
      forall x y : bool,&lt;br /&gt;
        x || y = true &amp;lt;-&amp;gt; x = true \/ y = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma dist_verdad_syss:&lt;br /&gt;
  forall x y : bool,&lt;br /&gt;
    x || y = true &amp;lt;-&amp;gt; x = true \/ y = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.           (* x, y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           x || y = true &amp;lt;-&amp;gt; x = true \/ y = true *)&lt;br /&gt;
  destruct x.&lt;br /&gt;
  -                     (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true || y = true &amp;lt;-&amp;gt; true = true \/ y = true *)&lt;br /&gt;
    simpl.              (* true = true &amp;lt;-&amp;gt; true = true \/ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true -&amp;gt; true = true \/ y = true *)&lt;br /&gt;
      apply disy_intro. &lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true \/ y = true -&amp;gt; true = true *)&lt;br /&gt;
      intros.           (* y : bool&lt;br /&gt;
                           H : true = true \/ y = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                     (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false || y = true &amp;lt;-&amp;gt; false = true \/ y = true *)&lt;br /&gt;
    simpl.              (* y = true &amp;lt;-&amp;gt; false = true \/ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true -&amp;gt; false = true \/ y = true *)&lt;br /&gt;
      destruct y.&lt;br /&gt;
      *                 (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true -&amp;gt; false = true \/ true = true *)&lt;br /&gt;
        intros.         (* H : true = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true \/ true = true *)&lt;br /&gt;
        right.          (* true = true *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                 (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; false = true \/ false = true *)&lt;br /&gt;
        apply disy_intro.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true \/ y = true -&amp;gt; y = true *)&lt;br /&gt;
      intros [H1 | H2].&lt;br /&gt;
      *                 (* y : bool&lt;br /&gt;
                           H1 : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true *)&lt;br /&gt;
        inversion H1.&lt;br /&gt;
      *                 (* y : bool&lt;br /&gt;
                           H2 : y = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
        &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.3. Demostrar que&lt;br /&gt;
      forall x y : nat,&lt;br /&gt;
        iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_falso_syss:&lt;br /&gt;
  forall x y : nat,&lt;br /&gt;
    iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.                           (* x, y : nat&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
  destruct (iguales_nat x y) eqn:H.&lt;br /&gt;
  -                                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = true&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    rewrite iguales_nat_bool_prop in H. (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    rewrite H.                          (* true = false &amp;lt;-&amp;gt; y &amp;lt;&amp;gt; y *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false -&amp;gt; y &amp;lt;&amp;gt; y *)&lt;br /&gt;
      intros H1.                        (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : true = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           y &amp;lt;&amp;gt; y *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           y &amp;lt;&amp;gt; y -&amp;gt; true = false *)&lt;br /&gt;
      intros H1.                        (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : y &amp;lt;&amp;gt; y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false *)&lt;br /&gt;
      exfalso.                          (* False *)&lt;br /&gt;
      unfold not in H1.                 (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : y = y -&amp;gt; False&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      apply H1.                         (* y = y *)&lt;br /&gt;
      apply eq_refl.&lt;br /&gt;
  -                                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false -&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
      unfold not.                       (* false = false -&amp;gt; x = y -&amp;gt; False *)&lt;br /&gt;
      intros H1 H2.                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      rewrite H2 in H.                  (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat y y = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      rewrite iguales_nat_refl in H.    (* x, y : nat&lt;br /&gt;
                                           H : true = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           x &amp;lt;&amp;gt; y -&amp;gt; false = false *)&lt;br /&gt;
      intros.                           (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           H0 : x &amp;lt;&amp;gt; y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.4.1. Definir la función &lt;br /&gt;
      iguales_lista {A : Type} (i : A -&amp;gt; A -&amp;gt; bool) (xs ys : list A)&lt;br /&gt;
   tal que (iguales_lists xs ys) se verifica si los correspondientes&lt;br /&gt;
   elementos de las listas xs e ys son iguales respecto de la relación&lt;br /&gt;
   de igualdad i.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_lista {A : Type} (i : A -&amp;gt; A -&amp;gt; bool) (xs ys : list A) : bool :=&lt;br /&gt;
  match xs, ys with&lt;br /&gt;
  | nil, nil            =&amp;gt; true&lt;br /&gt;
  | x&amp;#039; ::xs&amp;#039;, y&amp;#039; :: ys&amp;#039; =&amp;gt; i x&amp;#039; y&amp;#039; &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039;&lt;br /&gt;
  | _, _                =&amp;gt; false                          &lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.4.2. Demostrar que&lt;br /&gt;
      forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
        (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
        forall xs ys, iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs = ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_CN:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, iguales_lista i xs ys = true -&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs.                  (* A : Type&lt;br /&gt;
                                       i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                       H : forall x y : A, &lt;br /&gt;
                                            i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                       xs : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i xs ys = true -&amp;gt; xs=ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HIxs&amp;#039;].&lt;br /&gt;
  -                                 (* A : Type&lt;br /&gt;
                                       i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                       H : forall x y : A, &lt;br /&gt;
                                            i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i [ ] ys = true -&amp;gt; &lt;br /&gt;
                                        [ ] = ys *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                               (* iguales_lista i [ ] [ ] = true -&amp;gt; &lt;br /&gt;
                                       [ ] = [ ] *)&lt;br /&gt;
      intros.                       (*   H0 : iguales_lista i [ ] [ ] = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       [ ] = [ ] *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                               (* y : A&lt;br /&gt;
                                       ys&amp;#039; : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       iguales_lista i [ ] (y :: ys&amp;#039;) = true &lt;br /&gt;
                                       -&amp;gt; [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      simpl.                        (* false = true -&amp;gt; [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      intros H1.                    (* H1 : false = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                                 (* x : A&lt;br /&gt;
                                       xs&amp;#039; : list A&lt;br /&gt;
                                       HIxs&amp;#039; : forall ys : list A, &lt;br /&gt;
                                                iguales_lista i xs&amp;#039; ys = true &lt;br /&gt;
                                                -&amp;gt; xs&amp;#039; = ys&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i (x :: xs&amp;#039;) ys = true &lt;br /&gt;
                                        -&amp;gt; x :: xs&amp;#039; = ys *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                               (* iguales_lista i (x :: xs&amp;#039;) [ ] = true &lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      simpl.                        (* false = true -&amp;gt; x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      intros H1.                    (* H1 : false = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                               (* y : A&lt;br /&gt;
                                       ys&amp;#039; : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       iguales_lista i (x::xs&amp;#039;) (y::ys&amp;#039;) = true&lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      simpl.                        (* i x y &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      intros H1.                    (* H1 : i x y &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039; = &lt;br /&gt;
                                            true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      apply conj_verdad_syss in H1. (* H1 : i x y = true /\ &lt;br /&gt;
                                            iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      destruct H1 as [H2 H3].       (* H2 : i x y = true&lt;br /&gt;
                                       H3 : iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      f_equal.&lt;br /&gt;
      *                             (* x = y *)&lt;br /&gt;
        apply H.                    (* i x y = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
      *                             (* xs&amp;#039; = ys&amp;#039; *)&lt;br /&gt;
        apply HIxs&amp;#039;.                (* iguales_lista i xs&amp;#039; ys&amp;#039; = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_CS:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, xs = ys -&amp;gt; iguales_lista i xs ys = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs.                (* A : Type&lt;br /&gt;
                                     i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                     H : forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                     xs : list A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall ys : &lt;br /&gt;
                                      list A, xs = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i xs ys = true *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HIxs&amp;#039;]. &lt;br /&gt;
  -                               (* forall ys : &lt;br /&gt;
                                      list A, [ ] = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i [ ] ys = true *)&lt;br /&gt;
    intros ys H1.                 (* ys : list A&lt;br /&gt;
                                     H1 : [ ] = ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     iguales_lista i [ ] ys = true *)&lt;br /&gt;
    rewrite &amp;lt;- H1.                 (* iguales_lista i [ ] [ ] = true *)&lt;br /&gt;
    simpl.                        (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                               (* x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HIxs&amp;#039; : forall ys : &lt;br /&gt;
                                              list A, xs&amp;#039; = ys -&amp;gt; &lt;br /&gt;
                                              iguales_lista i xs&amp;#039; ys = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall ys : &lt;br /&gt;
                                      list A, x :: xs&amp;#039; = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i (x :: xs&amp;#039;) ys = true *)&lt;br /&gt;
    intros ys H1.                 (* ys : list A&lt;br /&gt;
                                     H1 : x :: xs&amp;#039; = ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     iguales_lista i (x :: xs&amp;#039;) ys = true *)&lt;br /&gt;
    rewrite &amp;lt;-H1.                  (* iguales_lista i (x::xs&amp;#039;) (x::xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                        (* i x x &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    apply conj_verdad_syss.       (* i x x = true /\ &lt;br /&gt;
                                     iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                             (* i x x = true *)&lt;br /&gt;
      apply H.                    (* x = x *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                             (* iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
      apply HIxs&amp;#039;.                (* xs&amp;#039; = xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_syss:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs ys.              (* A : Type&lt;br /&gt;
                                      i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                      H : forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                      xs, ys : list A&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs=ys *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                                (* iguales_lista i xs ys = true -&amp;gt; xs = ys *)&lt;br /&gt;
    apply iguales_lista_verdad_CN. (* forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                                (* xs = ys -&amp;gt; iguales_lista i xs ys = true *)&lt;br /&gt;
    apply iguales_lista_verdad_CS. (* forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y *)&lt;br /&gt;
    apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.5. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
        todos p xs = true &amp;lt;-&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_CN:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    todos p xs = true -&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.                 (* X : Type&lt;br /&gt;
                                    p : X -&amp;gt; bool&lt;br /&gt;
                                    xs : list X&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    todos p xs = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].&lt;br /&gt;
  -                              (* todos p [ ] = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) [ ] *)&lt;br /&gt;
    simpl.                       (* true = true -&amp;gt; True *)&lt;br /&gt;
    intros.                      (* H : true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    True *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* x&amp;#039; : X&lt;br /&gt;
                                    xs&amp;#039; : list X&lt;br /&gt;
                                    HI : todos p xs&amp;#039; = true -&amp;gt; &lt;br /&gt;
                                         Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    todos p (x&amp;#039; :: xs&amp;#039;) = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) (x&amp;#039;::xs&amp;#039;) *)&lt;br /&gt;
    simpl.                       (* p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true -&amp;gt;&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    intros H.                    (* H : p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    apply conj_verdad_syss in H. (* H :p x&amp;#039; = true /\ todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    destruct H as [H1 H2].       (* H1 : p x&amp;#039; = true&lt;br /&gt;
                                    H2 : todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                            (* p x&amp;#039; = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
      apply HI.                  (* todos p xs&amp;#039; = true *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_CS:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    Todos (fun x =&amp;gt; p x = true) xs -&amp;gt; todos p xs = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.                (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) xs -&amp;gt; &lt;br /&gt;
                                   todos p xs = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* Todos (fun x : X =&amp;gt; p x = true) [ ] -&amp;gt; &lt;br /&gt;
                                   todos p [ ] = true *)&lt;br /&gt;
    simpl.                      (* True -&amp;gt; true = true *)&lt;br /&gt;
    intros.                     (* H : True&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        todos p xs&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) (x&amp;#039; :: xs&amp;#039;) &lt;br /&gt;
                                   -&amp;gt; todos p (x&amp;#039; :: xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                      (* p x&amp;#039; = true /\ &lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; -&amp;gt;&lt;br /&gt;
                                   p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true *)&lt;br /&gt;
    intros [H1 H2].             (* H1 : p x&amp;#039; = true&lt;br /&gt;
                                   H2 : Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true *)&lt;br /&gt;
    apply conj_verdad_syss.     (* p x&amp;#039; = true /\ todos p xs&amp;#039; = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                           (* p x&amp;#039; = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                           (* todos p xs&amp;#039; = true *)&lt;br /&gt;
      apply HI.                 (* Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_syss:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    todos p xs = true &amp;lt;-&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.           (* X : Type&lt;br /&gt;
                              p : X -&amp;gt; bool&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              ============================&lt;br /&gt;
                              todos p xs = true &amp;lt;-&amp;gt; &lt;br /&gt;
                              Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                        (* todos p xs = true -&amp;gt; &lt;br /&gt;
                              Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
    apply todos_verdad_CN. &lt;br /&gt;
  -                        (* Todos (fun x : X =&amp;gt; p x = true) xs -&amp;gt; &lt;br /&gt;
                              todos p xs = true *)&lt;br /&gt;
    apply todos_verdad_CS.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.3. Lógica clásica vs. constructiva  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.1. Definir la proposicion&lt;br /&gt;
      tercio_excluso&lt;br /&gt;
   que afirma que  (forall P : Prop, P \/ ~ P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Definition tercio_excluso : Prop := forall P : Prop,&lt;br /&gt;
  P \/ ~ P.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La proposión tercio_excluso no es demostrable en Coq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.2. Demostrar que&lt;br /&gt;
      forall (P : Prop) (b : bool),&lt;br /&gt;
        (P &amp;lt;-&amp;gt; b = true) -&amp;gt; P \/ ~ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_exluso_restringido :&lt;br /&gt;
  forall (P : Prop) (b : bool),&lt;br /&gt;
    (P &amp;lt;-&amp;gt; b = true) -&amp;gt; P \/ ~ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P [] H.  &lt;br /&gt;
  -               (* P : Prop&lt;br /&gt;
                     H : P &amp;lt;-&amp;gt; true = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     P \/ ~ P *)&lt;br /&gt;
    left.         (* P *)&lt;br /&gt;
    rewrite H.    (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* P : Prop&lt;br /&gt;
                     H : P &amp;lt;-&amp;gt; false = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     P \/ ~ P *)&lt;br /&gt;
    right.        (* ~ P *)&lt;br /&gt;
    rewrite H.    (* false &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H1.    (* H1 : false = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
    inversion H1. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        n = m \/ n &amp;lt;&amp;gt; m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_exluso_restringido_eq:&lt;br /&gt;
  forall (n m : nat),&lt;br /&gt;
    n = m \/ n &amp;lt;&amp;gt; m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                      (* n, m : nat&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      n = m \/ n &amp;lt;&amp;gt; m *)&lt;br /&gt;
  apply (tercio_exluso_restringido &lt;br /&gt;
           (n = m)&lt;br /&gt;
           (iguales_nat n m)).     (* n = m &amp;lt;-&amp;gt; iguales_nat n m = true *)&lt;br /&gt;
  symmetry.                        (* iguales_nat n m = true &amp;lt;-&amp;gt; n = m *)&lt;br /&gt;
  apply iguales_nat_bool_prop.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En Coq no se puede demostrar el principio del tercio exluso.&lt;br /&gt;
   2. Las demostraciones de las fórmulas existenciales tienen que&lt;br /&gt;
      proporcionar un testigo.&lt;br /&gt;
   2. la lógica de Coq es constructiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.1. Demostrar que&lt;br /&gt;
      forall (P : Prop),&lt;br /&gt;
        ~ ~ (P \/ ~ P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_irrefutable:&lt;br /&gt;
  forall (P : Prop),&lt;br /&gt;
    ~ ~ (P \/ ~ P).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P.   (* P : Prop&lt;br /&gt;
                 ============================&lt;br /&gt;
                 ~ ~ (P \/ ~ P) *)&lt;br /&gt;
  unfold not. (* (P \/ (P -&amp;gt; False) -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros H.   (* H : P \/ (P -&amp;gt; False) -&amp;gt; False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply H.    (* P \/ (P -&amp;gt; False) *)&lt;br /&gt;
  right.      (* P -&amp;gt; False *)&lt;br /&gt;
  intro H1.   (* H1 : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply H.    (* P \/ (P -&amp;gt; False) *)&lt;br /&gt;
  left.       (* P *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El teorema anterior garantiza que añadir el tercio excluso como&lt;br /&gt;
   axioma no provoca contradicción.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.2. Demostrar que&lt;br /&gt;
      tercio_excluso -&amp;gt;&lt;br /&gt;
      forall (X : Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
        ~ (exists x, ~ P x) -&amp;gt; (forall x, P x).&lt;br /&gt;
&lt;br /&gt;
   Nota. La condición del tercio_excluso es necesaria.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem no_existe_no:&lt;br /&gt;
  tercio_excluso -&amp;gt;&lt;br /&gt;
  forall (X : Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
    ~ (exists x, ~ P x) -&amp;gt; (forall x, P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 X P H2 x.          (* H1 : tercio_excluso&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  P : X -&amp;gt; Prop&lt;br /&gt;
                                  H2 : ~ (exists x : X, ~ P x)&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
  unfold tercio_excluso in H1. (* H1 : forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  assert (P x \/ ~ P x).&lt;br /&gt;
  -                            (* P x \/ ~ P x *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                            (* H : P x \/ ~ P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
    destruct H as [H3 | H4].&lt;br /&gt;
    +                          (* x : X&lt;br /&gt;
                                  H3 : P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                          (* x : X&lt;br /&gt;
                                  H4 : ~ P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
      exfalso.                 (* False *)&lt;br /&gt;
      apply H2.                (* exists x0 : X, ~ P x0 *)&lt;br /&gt;
      exists x.                     (* ~ P x *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.1. En este ejercico se van a demostrar 4 formas&lt;br /&gt;
   equivalentes del principio del tercio excluso. &lt;br /&gt;
&lt;br /&gt;
   Sea peirce la proposición definida por&lt;br /&gt;
      Definition peirce: Prop := forall P Q : Prop,&lt;br /&gt;
        ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; peirce &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition peirce: Prop := forall P Q : Prop,&lt;br /&gt;
  ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_peirce_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; peirce.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.     (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                (forall P : Prop, P \/ ~ P) -&amp;gt; peirce *)&lt;br /&gt;
  unfold peirce.             (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P *)&lt;br /&gt;
  intros H1 P Q H2.          (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                P, Q : Prop&lt;br /&gt;
                                H2 : (P -&amp;gt; Q) -&amp;gt; P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                          (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* H : P \/ ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                        (* H3 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                        (* H4 : ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
      apply H2.              (* P -&amp;gt; Q *)&lt;br /&gt;
      intros H5.             (* H5 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
      exfalso.               (* False *)&lt;br /&gt;
      apply H4.              (* P *)&lt;br /&gt;
      apply H5.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_peirce_L2:&lt;br /&gt;
  peirce -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold peirce.         (* &lt;br /&gt;
                            ============================&lt;br /&gt;
                            (forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                            tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso. (* (forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                            forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H P.            (* H : forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P&lt;br /&gt;
                            P : Prop&lt;br /&gt;
                            ============================&lt;br /&gt;
                            P \/ ~ P *)&lt;br /&gt;
  apply H with (Q := False). (* (P \/ ~ P -&amp;gt; False) -&amp;gt; P \/ ~ P *)&lt;br /&gt;
  intros H1.             (* H1 : P \/ ~ P -&amp;gt; False&lt;br /&gt;
                            ============================&lt;br /&gt;
                            P \/ ~ P *)&lt;br /&gt;
  right.                 (* ~ P *)&lt;br /&gt;
  unfold not.            (* P -&amp;gt; False *)&lt;br /&gt;
  intros H2.             (* H2 : P&lt;br /&gt;
                            ============================&lt;br /&gt;
                            False *)&lt;br /&gt;
  apply H1.              (* P \/ ~ P *)&lt;br /&gt;
  left.                  (* P *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_peirce:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; peirce.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                                 (* &lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       tercio_excluso -&amp;gt; peirce *)&lt;br /&gt;
    apply tercio_excluso_peirce_L1. &lt;br /&gt;
  -                                 (* &lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       peirce -&amp;gt; tercio_excluso *)&lt;br /&gt;
    apply tercio_excluso_peirce_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.2. Sea eliminacion_doble_negacion la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition eliminacion_doble_negacion: Prop := forall P : Prop,&lt;br /&gt;
        ~~P -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; eliminacion_doble_negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition eliminacion_doble_negacion: Prop := forall P : Prop,&lt;br /&gt;
  ~~P -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; eliminacion_doble_negacion.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.             (* &lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                        eliminacion_doble_negacion *)&lt;br /&gt;
  unfold eliminacion_doble_negacion. (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                        forall P : Prop, ~ ~ P -&amp;gt; P *)&lt;br /&gt;
  intros H1 P H2.                    (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                        P : Prop&lt;br /&gt;
                                        H2 : ~ ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                                  (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                  (* H : P \/ ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
    destruct H as [H3 | H4].&lt;br /&gt;
    +                                (* H2 : ~ ~ P&lt;br /&gt;
                                        H3 : P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                                (* H4 : ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
      exfalso.                       (* False *)&lt;br /&gt;
      apply H2.                      (* ~ P *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion_L2:&lt;br /&gt;
  eliminacion_doble_negacion -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold eliminacion_doble_negacion. (* &lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        (forall P : Prop, ~ ~ P -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                                        tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.             (* (forall P : Prop, ~ ~ P -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                                        forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H P.                        (* H : forall P : Prop, ~ ~ P -&amp;gt; P&lt;br /&gt;
                                        P : Prop&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P \/ ~ P *)&lt;br /&gt;
  apply H.                           (* ~ ~ (P \/ ~ P) *)&lt;br /&gt;
  apply tercio_excluso_irrefutable.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; eliminacion_doble_negacion.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_eliminacion_doble_negacion_L1.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_eliminacion_doble_negacion_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.3. Sea morgan_no_no la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition de_morgan_no_no: Prop :=&lt;br /&gt;
        forall P Q : Prop, ~(~P /\ ~Q) -&amp;gt; P \/ Q.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; morgan_no_no&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition de_morgan_no_no: Prop :=&lt;br /&gt;
  forall P Q : Prop, ~(~P /\ ~Q) -&amp;gt; P \/ Q.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; de_morgan_no_no.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.     (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                de_morgan_no_no *)&lt;br /&gt;
  unfold de_morgan_no_no.    (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q *)&lt;br /&gt;
  intros H1 P Q H2.          (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                P, Q : Prop&lt;br /&gt;
                                H2 : ~ (~ P /\ ~ Q)&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                          (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* H : P \/ ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                        (* H2 : ~ (~ P /\ ~ Q)&lt;br /&gt;
                                H3 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
      left.                  (* P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                        (* H4 : ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
      right.                 (* Q *)&lt;br /&gt;
      assert (Q \/ ~ Q).&lt;br /&gt;
      *                      (* Q \/ ~ Q *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                      (* H : Q \/ ~ Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
        destruct H as [H5 | H6].&lt;br /&gt;
        --                   (* H5 : Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
          apply H5.&lt;br /&gt;
        --                   (* H6 : ~ Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
          exfalso.           (* False *)&lt;br /&gt;
          apply H2.          (* ~ P /\ ~ Q *)&lt;br /&gt;
          split.&lt;br /&gt;
          ++                 (* ~ P *)&lt;br /&gt;
            apply H4.&lt;br /&gt;
          ++                 (* ~ Q *)&lt;br /&gt;
            apply H6.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no_L2:&lt;br /&gt;
  de_morgan_no_no -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold de_morgan_no_no. (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             (forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q) -&amp;gt; &lt;br /&gt;
                             tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.  (* (forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q) -&amp;gt; &lt;br /&gt;
                             forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H1 P.            (* H1 : forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q&lt;br /&gt;
                             P : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ ~ P *)&lt;br /&gt;
  apply H1.               (* ~ (~ P /\ ~ ~ P) *)&lt;br /&gt;
  intros H2.              (* H2 : ~ P /\ ~ ~ P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             False *)&lt;br /&gt;
  destruct H2 as (H3,H4). (* H3 : ~ P&lt;br /&gt;
                             H4 : ~ ~ P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             False *)&lt;br /&gt;
  apply H4.               (* ~ P *)&lt;br /&gt;
  apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; de_morgan_no_no.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_de_morgan_no_no_L1.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_de_morgan_no_no_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.4. Sea condicional_a_disyuncion la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition condicional_a_disyuncion: Prop :=&lt;br /&gt;
        forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; (~P \/ Q).&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; morgan_no_no&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition condicional_a_disyuncion: Prop :=&lt;br /&gt;
  forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; (~P \/ Q).&lt;br /&gt;
&lt;br /&gt;
Lemma tercio_excluso_equiv_condicional_a_disyuncion_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; condicional_a_disyuncion.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.           (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                      condicional_a_disyuncion *)&lt;br /&gt;
  unfold condicional_a_disyuncion. (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                      forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q *)&lt;br /&gt;
  intros H1 P Q H2.                (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                      P, Q : Prop&lt;br /&gt;
                                      H2 : P -&amp;gt; Q&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                                (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                (* H : P \/ ~ P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                              (* H3 : P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
      right.                       (* Q *)&lt;br /&gt;
      apply H2.                    (* P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                              (* H4 : ~ P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
      left.                        (* ~ P *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma tercio_excluso_equiv_condicional_a_disyuncion_L2:&lt;br /&gt;
  condicional_a_disyuncion -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold condicional_a_disyuncion. (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      (forall P Q:Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q) &lt;br /&gt;
                                      -&amp;gt; tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.           (* (forall P Q:Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q) &lt;br /&gt;
                                      -&amp;gt; forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H1 P.                     (* H1 : forall P Q : Prop, &lt;br /&gt;
                                            (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q&lt;br /&gt;
                                      P : Prop&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      P \/ ~ P *)&lt;br /&gt;
  apply disy_conmutativa.          (* ~ P \/ P *)&lt;br /&gt;
  apply H1.                        (* P -&amp;gt; P *)&lt;br /&gt;
  intros.                          (* H : P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_condicional_a_disyuncion:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; condicional_a_disyuncion.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  - apply tercio_excluso_equiv_condicional_a_disyuncion_L1.&lt;br /&gt;
  - apply tercio_excluso_equiv_condicional_a_disyuncion_L2.&lt;br /&gt;
Qed.    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Logic.html Logic in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_6:_L%C3%B3gica_en_Coq&amp;diff=71</id>
		<title>Tema 6: Lógica en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_6:_L%C3%B3gica_en_Coq&amp;diff=71"/>
		<updated>2018-08-20T10:42:14Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página creada con «En este capítulo se amplía el campo de aplicación de Coq para todas las conectivas y cuantificadores de la lógica de primer orden.  = Teoría =  La teoría correspondie…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este capítulo se amplía el campo de aplicación de Coq para todas las conectivas y cuantificadores de la lógica de primer orden.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T6_Logica.v|T6_Logica.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T6: Lógica en Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T5_Tacticas.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. Introducción&lt;br /&gt;
   2. Conectivas lógicas &lt;br /&gt;
      1. Conjunción &lt;br /&gt;
      2. Disyunción  &lt;br /&gt;
      3. Falsedad y negación  &lt;br /&gt;
      4. Verdad&lt;br /&gt;
      5. Equivalencia lógica&lt;br /&gt;
      6. Cuantificación existencial  &lt;br /&gt;
   3. Programación con proposiciones &lt;br /&gt;
   4. Aplicando teoremas a argumentos &lt;br /&gt;
   5. Coq vs. teoría de conjuntos &lt;br /&gt;
      1. Extensionalidad funcional&lt;br /&gt;
      2. Proposiciones y booleanos  &lt;br /&gt;
      3. Lógica clásica vs. constructiva  &lt;br /&gt;
   Bibliografía&lt;br /&gt;
 *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Introducción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      3 = 3.&lt;br /&gt;
      3 = 4.&lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
      forall n : nat, n = 2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Check 3 = 3.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check 3 = 4.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check forall n m : nat, n + m = m + n.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check forall n : nat, n = 2.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El tipo de las fórmulas es Prop.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Demostrar que 2 más dos es 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_2_y_2:&lt;br /&gt;
  2 + 2 = 4.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Usa la proposición &amp;#039;2 + 2 = 4&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la proposición &lt;br /&gt;
      prop_suma: Prop&lt;br /&gt;
   que afirma que la suma de 2 y 2 es 4. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prop_suma: Prop := 2 + 2 = 4.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Calcular el tipo de prop_suma&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check prop_suma.&lt;br /&gt;
(* ===&amp;gt; prop_suma : Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Usando prop_suma, demostrar que la suma de 2 y 2 es 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_suma_es_verdadera:&lt;br /&gt;
  prop_suma.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Definir la proposición &lt;br /&gt;
      es_tres (n : nat) : Prop&lt;br /&gt;
   tal que (es_tres n) se verifica si n es el número 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition es_tres (n : nat) : Prop :=&lt;br /&gt;
  n = 3.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.2. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      es_tres.&lt;br /&gt;
      es_tres 3.&lt;br /&gt;
      es_tres 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres.&lt;br /&gt;
(* ===&amp;gt; nat -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres 3.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check es_tres 5.&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Ejemplo de proposición parametrizada.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir la función&lt;br /&gt;
      inyectiva {A B : Type} (f : A -&amp;gt; B) : Prop :=&lt;br /&gt;
   tal que (inyectiva f) se verifica si f es inyectiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition inyectiva {A B : Type} (f : A -&amp;gt; B) : Prop :=&lt;br /&gt;
  forall x y : A, f x = f y -&amp;gt; x = y.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Demostrar que la funcion sucesor es inyectiva; es&lt;br /&gt;
   decir, &lt;br /&gt;
      inyectiva S.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma suc_iny: inyectiva S.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5. Calcular los tipos de las siguientes expresiones&lt;br /&gt;
      3 = 5.&lt;br /&gt;
      eq 3 5.&lt;br /&gt;
      eq 3.&lt;br /&gt;
      @eq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (3 = 5).&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check (eq 3 5).&lt;br /&gt;
(* ===&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check (eq 3).&lt;br /&gt;
(* ===&amp;gt; nat -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
Check @eq.&lt;br /&gt;
(* ===&amp;gt; forall A : Type, A -&amp;gt; A -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. La expresión (x = y) es una abreviatura de (eq x y).&lt;br /&gt;
   2. Se escribe @eq en lugar de eq para ver los argumentos implícitos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Conectivas lógicas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.1. Conjunción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que&lt;br /&gt;
      3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ej_conjuncion: 3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.         &lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    3 + 4 = 7 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    2 * 2 = 4 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. El símbolo de conjunción se escribe con /\&lt;br /&gt;
   2. La táctica &amp;#039;split&amp;#039; sustituye el objetivo (P /\ Q) por los&lt;br /&gt;
   subobjetivos P y Q. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que&lt;br /&gt;
      forall A B : Prop, A -&amp;gt; B -&amp;gt; A /\ B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_intro: forall A B : Prop, A -&amp;gt; B -&amp;gt; A /\ B.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B HA HB. (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       A /\ B *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                 (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       A *)&lt;br /&gt;
    apply HA.&lt;br /&gt;
  -                 (* A, B : Prop&lt;br /&gt;
                       HA : A&lt;br /&gt;
                       HB : B&lt;br /&gt;
                       ============================&lt;br /&gt;
                       B *)&lt;br /&gt;
    apply HB.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar, con con_intro, que&lt;br /&gt;
      3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ej_conjuncion&amp;#039;: 3 + 4 = 7 /\ 2 * 2 = 4.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply conj_intro. &lt;br /&gt;
  -                 (* 3 + 4 = 7 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* 2 * 2 = 4 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.1. Demostrar que&lt;br /&gt;
      forall n m : nat, n + m = 0 -&amp;gt; n = 0 /\ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_conj:&lt;br /&gt;
  forall n m : nat, n + m = 0 -&amp;gt; n = 0 /\ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.                      (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        n = 0 /\ m = 0 *)&lt;br /&gt;
  apply conj_intro.&lt;br /&gt;
  -                                  (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        n = 0 *)&lt;br /&gt;
    destruct n.&lt;br /&gt;
    +                                (* m : nat&lt;br /&gt;
                                        H : 0 + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                (* n, m : nat&lt;br /&gt;
                                        H : S n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S n = 0 *)&lt;br /&gt;
      simpl in H.                    (* n, m : nat&lt;br /&gt;
                                        H : S (n + m) = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S n = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                                  (* n, m : nat&lt;br /&gt;
                                        H : n + m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        m = 0 *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                                (* n : nat&lt;br /&gt;
                                        H : n + 0 = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                (* n, m : nat&lt;br /&gt;
                                        H : n + S m = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      rewrite suma_conmutativa in H. (* n, m : nat&lt;br /&gt;
                                        H : S m + n = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      simpl in H.                    (* n, m : nat&lt;br /&gt;
                                        H : S (m + n) = 0&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        S m = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.4. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2 :&lt;br /&gt;
  forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.          (* n, m : nat&lt;br /&gt;
                            H : n = 0 /\ m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  destruct H as [Hn Hm]. (* n, m : nat&lt;br /&gt;
                            Hn : n = 0&lt;br /&gt;
                            Hm : m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  rewrite Hn.            (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.            (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct H as [HA HB]&amp;#039; que  sustituye la&lt;br /&gt;
   hipótesis H de la forma (A /\ B) por las hipótesis HA (que afirma&lt;br /&gt;
   que A es verdad) y HB (que afirma que B es verdad).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.5. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2&amp;#039; :&lt;br /&gt;
  forall n m : nat, n = 0 /\ m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m [Hn Hm].    (* n, m : nat&lt;br /&gt;
                            Hn : n = 0&lt;br /&gt;
                            Hm : m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n + m = 0 *)&lt;br /&gt;
  rewrite Hn.            (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.            (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;intros x [HA HB]&amp;#039;, cuando el objetivo es de la&lt;br /&gt;
   forma (forall x, A /\ B -&amp;gt; C), introduce la variable x y las&lt;br /&gt;
   hipótesis HA y HB afirmando la certeza de A y de B, respectivamente.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.6. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 -&amp;gt; m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion2&amp;#039;&amp;#039; :&lt;br /&gt;
  forall n m : nat, n = 0 -&amp;gt; m = 0 -&amp;gt; n + m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m Hn Hm. (* n, m : nat&lt;br /&gt;
                       Hn : n = 0&lt;br /&gt;
                       Hm : m = 0&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n + m = 0 *)&lt;br /&gt;
  rewrite Hn.       (* 0 + m = 0 *)&lt;br /&gt;
  rewrite Hm.       (* 0 + 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.7. Demostrar que&lt;br /&gt;
      forall n m : nat, n + m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_conjuncion3 :&lt;br /&gt;
  forall n m : nat, n + m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.                (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
  assert (H&amp;#039; : n = 0 /\ m = 0). &lt;br /&gt;
  -                            (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n = 0 /\ m = 0 *)&lt;br /&gt;
    apply ejercicio_conj.      (* n + m = 0 *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                            (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  H&amp;#039; : n = 0 /\ m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
    destruct H&amp;#039; as [Hn Hm].    (* n, m : nat&lt;br /&gt;
                                  H : n + m = 0&lt;br /&gt;
                                  Hn : n = 0&lt;br /&gt;
                                  Hm : m = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  n * m = 0 *)&lt;br /&gt;
    rewrite Hn.                (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.8. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_e1 : forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         P *)&lt;br /&gt;
  apply HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.2. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_e2: forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; Q.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q *)&lt;br /&gt;
  apply HQ.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.9. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P /\ Q -&amp;gt; Q /\ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conj_conmutativa: forall P Q : Prop,&lt;br /&gt;
  P /\ Q -&amp;gt; Q /\ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HQ]. (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q /\ P *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                   (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Q *)&lt;br /&gt;
    apply HQ.&lt;br /&gt;
  -                   (* P, Q : Prop&lt;br /&gt;
                         HP : P&lt;br /&gt;
                         HQ : Q&lt;br /&gt;
                         ============================&lt;br /&gt;
                         P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1.3. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        P /\ (Q /\ R) -&amp;gt; (P /\ Q) /\ R.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conj_asociativa : forall P Q R : Prop,&lt;br /&gt;
  P /\ (Q /\ R) -&amp;gt; (P /\ Q) /\ R.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R [HP [HQ HR]]. (* P, Q, R : Prop&lt;br /&gt;
                                HP : P&lt;br /&gt;
                                HQ : Q&lt;br /&gt;
                                HR : R&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (P /\ Q) /\ R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                          (* P /\ Q *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                        (* P *)&lt;br /&gt;
      apply HP.&lt;br /&gt;
    +                        (* Q *)&lt;br /&gt;
      apply HQ.&lt;br /&gt;
  -                          (* R *)&lt;br /&gt;
    apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;intros P Q R [HP [HQ HR]]&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.10. Calcular el tipo de la expresión&lt;br /&gt;
      and&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check and.&lt;br /&gt;
(* ===&amp;gt; and : Prop -&amp;gt; Prop -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. (x /\ y) es una abreviatura de (and x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.2. Disyunción  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Lemma disy_ej1:&lt;br /&gt;
  forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.&lt;br /&gt;
  destruct H as [Hn | Hm]. &lt;br /&gt;
  -                        (* n, m : nat&lt;br /&gt;
                              Hn : n = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * m = 0 *)&lt;br /&gt;
    rewrite Hn.            (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.           &lt;br /&gt;
  -                        (* n, m : nat&lt;br /&gt;
                              Hm : m = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * m = 0 *)&lt;br /&gt;
    rewrite Hm.            (* n * 0 = 0 *)&lt;br /&gt;
    rewrite &amp;lt;- mult_n_O.    (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Lemma disy_ej:&lt;br /&gt;
  forall n m : nat, n = 0 \/ m = 0 -&amp;gt; n * m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m [Hn | Hm]. &lt;br /&gt;
  -                     (* n, m : nat&lt;br /&gt;
                           Hn : n = 0&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n * m = 0 *)&lt;br /&gt;
    rewrite Hn.         (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n, m : nat&lt;br /&gt;
                           Hm : m = 0&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n * m = 0 *)&lt;br /&gt;
    rewrite Hm.         (* n * 0 = 0 *)&lt;br /&gt;
    rewrite &amp;lt;- mult_n_O. (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. La táctica &amp;#039;destruct H as [Hn | Hm]&amp;#039;, cuando la hipótesis H es de&lt;br /&gt;
      la forma (A \/ B), la divide en dos casos: uno con hipótesis HA&lt;br /&gt;
      (afirmando la certeza de A) y otro con la hipótesis HB (afirmando&lt;br /&gt;
      la certeza de B).   &lt;br /&gt;
   2. La táctica &amp;#039;intros x [HA | HB]&amp;#039;, cuando el objetivo es de la&lt;br /&gt;
      forma (forall x, A \/ B -&amp;gt; C), intoduce la variable x y dos casos:&lt;br /&gt;
      uno con hipótesis HA (afirmando la certeza de A) y otro con la&lt;br /&gt;
      hipótesis HB (afirmando la certeza de B).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que&lt;br /&gt;
      forall A B : Prop, A -&amp;gt; A \/ B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma disy_intro: forall A B : Prop, A -&amp;gt; A \/ B.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B HA. (* A, B : Prop&lt;br /&gt;
                    HA : A&lt;br /&gt;
                    ============================&lt;br /&gt;
                    A \/ B *)&lt;br /&gt;
  left.          (* A *)&lt;br /&gt;
  apply HA.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;left&amp;#039; sustituye el objetivo de la forma (A \/ B)&lt;br /&gt;
   por A.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.3. Demostrar que&lt;br /&gt;
      forall n : nat, n = 0 \/ n = S (pred n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cero_o_sucesor:&lt;br /&gt;
  forall n : nat, n = 0 \/ n = S (pred n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    0 = 0 \/ 0 = S (Nat.pred 0) *)&lt;br /&gt;
    left.        (* 0 = 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* n : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    S n = 0 \/ S n = S (Nat.pred (S n)) *)&lt;br /&gt;
    right.       (* S n = S (Nat.pred (S n)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;right&amp;#039; sustituye el objetivo de la forma (A \/ B)&lt;br /&gt;
   por B.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que&lt;br /&gt;
      forall n m, n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_eq_0 :&lt;br /&gt;
  forall n m, n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.          (* n, m : nat&lt;br /&gt;
                            H : n * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            n = 0 \/ m = 0 *)&lt;br /&gt;
  destruct n as [|n&amp;#039;].&lt;br /&gt;
  -                      (* m : nat&lt;br /&gt;
                            H : 0 * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 = 0 \/ m = 0 *)&lt;br /&gt;
    left.                (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n&amp;#039;, m : nat&lt;br /&gt;
                            H : S n&amp;#039; * m = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ m = 0 *)&lt;br /&gt;
    destruct m as [|m&amp;#039;]. &lt;br /&gt;
    +                    (* n&amp;#039; : nat&lt;br /&gt;
                            H : S n&amp;#039; * 0 = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ 0 = 0 *)&lt;br /&gt;
      right.             (* 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                            H : S n&amp;#039; * S m&amp;#039; = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ S m&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.        (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                            H : S (m&amp;#039; + n&amp;#039; * S m&amp;#039;) = 0&lt;br /&gt;
                            ============================&lt;br /&gt;
                            S n&amp;#039; = 0 \/ S m&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        P \/ Q  -&amp;gt; Q \/ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem disy_conmutativa: forall P Q : Prop,&lt;br /&gt;
  P \/ Q  -&amp;gt; Q \/ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP | HQ]. &lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HP : P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q \/ P *)&lt;br /&gt;
    right.              (* P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HQ : Q&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q \/ P *)&lt;br /&gt;
    left.               (* Q *)&lt;br /&gt;
    apply HQ.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.4. Calcular el tipo de la expresión&lt;br /&gt;
      or&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check or.&lt;br /&gt;
(* ===&amp;gt; or : Prop -&amp;gt; Prop -&amp;gt; Prop *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. (x \/ y) es una abreviatura de (or x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.3. Falsedad y negación  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module DefNot.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Definir la función&lt;br /&gt;
      not (P : Prop) : Prop&lt;br /&gt;
   tal que (not P) es la negación de P&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition not (P:Prop) : Prop :=&lt;br /&gt;
    P -&amp;gt; False.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Definir (~ x) como abreviatura de (not x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;~ x&amp;quot; := (not x) : type_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Esta es la forma como está definida la negación en Coq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End DefNot.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que&lt;br /&gt;
      forall (P:Prop),&lt;br /&gt;
        False -&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ex_falso_quodlibet: forall (P:Prop),&lt;br /&gt;
  False -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 P *)&lt;br /&gt;
  destruct H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. En latín, &amp;quot;ex falso quodlibet&amp;quot; significa &amp;quot;de lo falso (se&lt;br /&gt;
   sigue) cualquier cosa&amp;quot;. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.1. Demostrar que&lt;br /&gt;
      forall (P:Prop),&lt;br /&gt;
        ~ P -&amp;gt; (forall (Q:Prop), P -&amp;gt; Q).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact negacion_elim: forall (P:Prop),&lt;br /&gt;
  ~ P -&amp;gt; (forall (Q:Prop), P -&amp;gt; Q).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.     (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     forall P : Prop, (P -&amp;gt; False) -&amp;gt; forall Q : Prop, P -&amp;gt; Q *)&lt;br /&gt;
  intros P H1.    (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     ============================&lt;br /&gt;
                     forall Q : Prop, P -&amp;gt; Q *)&lt;br /&gt;
  intros Q H2.    (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     Q : Prop&lt;br /&gt;
                     H2 : P&lt;br /&gt;
                     ============================&lt;br /&gt;
                     Q *)&lt;br /&gt;
  apply H1 in H2. (* P : Prop&lt;br /&gt;
                     H1 : P -&amp;gt; False&lt;br /&gt;
                     Q : Prop&lt;br /&gt;
                     H2 : False&lt;br /&gt;
                     ============================&lt;br /&gt;
                     Q *)&lt;br /&gt;
  destruct H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que&lt;br /&gt;
      ~(0 = 1).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_no_es_uno: ~(0 = 1).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H.       (* H : 0 = 1&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La expresión (x &amp;lt;&amp;gt; y) es una abreviatura de ~(x = y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem cero_no_es_uno&amp;#039;: 0 &amp;lt;&amp;gt; 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H.       (* H : 0 = 1&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
  inversion H. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que&lt;br /&gt;
      ~ False&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem not_False :&lt;br /&gt;
  ~ False.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not. (* &lt;br /&gt;
                 ============================&lt;br /&gt;
                 False -&amp;gt; False *)&lt;br /&gt;
  intros H.   (* H : False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  destruct H. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        (P /\ ~P) -&amp;gt; Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem contradiccion_implica_cualquiera: forall P Q : Prop,&lt;br /&gt;
  (P /\ ~P) -&amp;gt; Q.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HP HNP]. (* P, Q : Prop&lt;br /&gt;
                          HP : P&lt;br /&gt;
                          HNP : ~ P&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  unfold not in HNP. (* P, Q : Prop&lt;br /&gt;
                          HP : P&lt;br /&gt;
                          HNP : P -&amp;gt; False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  apply HNP in HP. (* P, Q : Prop&lt;br /&gt;
                          HP : False&lt;br /&gt;
                          HNP : P -&amp;gt; False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          Q *)&lt;br /&gt;
  destruct HP.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.7. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        P -&amp;gt; ~~P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem doble_neg: forall P : Prop,&lt;br /&gt;
  P -&amp;gt; ~~P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 ~ ~ P *)&lt;br /&gt;
  unfold not. (* (P -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros G.   (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 G : P -&amp;gt; False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply G.    (* P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.2. Demostrar que&lt;br /&gt;
      forall (P Q : Prop),&lt;br /&gt;
        (P -&amp;gt; Q) -&amp;gt; (~Q -&amp;gt; ~P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem contrapositiva: forall (P Q : Prop),&lt;br /&gt;
  (P -&amp;gt; Q) -&amp;gt; (~Q -&amp;gt; ~P).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.          (* &lt;br /&gt;
                          ============================&lt;br /&gt;
                          forall P Q : Prop, &lt;br /&gt;
                            (P -&amp;gt; Q) -&amp;gt; (Q -&amp;gt; False) -&amp;gt; P -&amp;gt; False *)&lt;br /&gt;
  intros P Q H1 H2 H3. (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : P&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H1 in H3.      (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : Q&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H2 in H3.      (* P, Q : Prop&lt;br /&gt;
                          H1 : P -&amp;gt; Q&lt;br /&gt;
                          H2 : Q -&amp;gt; False&lt;br /&gt;
                          H3 : False&lt;br /&gt;
                          ============================&lt;br /&gt;
                          False *)&lt;br /&gt;
  apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.3. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        ~ (P /\ ~P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem no_contradiccion: forall P : Prop,&lt;br /&gt;
  ~ (P /\ ~P).&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold not.       (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       forall P : Prop, P /\ (P -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros P [H1 H2]. (* P : Prop&lt;br /&gt;
                       H1 : P&lt;br /&gt;
                       H2 : P -&amp;gt; False&lt;br /&gt;
                       ============================&lt;br /&gt;
                       False *)&lt;br /&gt;
  apply H2.         (* P *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.8. Demostrar que&lt;br /&gt;
      forall b : bool,&lt;br /&gt;
        b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem no_verdadero_es_falso: forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] H.&lt;br /&gt;
  -                           (* H : true &amp;lt;&amp;gt; true&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = false *)&lt;br /&gt;
    unfold not in H.          (* H : true = true -&amp;gt; False&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = false *)&lt;br /&gt;
    apply ex_falso_quodlibet. (* H : true = true -&amp;gt; False&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 False *)&lt;br /&gt;
    apply H.                  (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* H : false &amp;lt;&amp;gt; true&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem no_verdadero_es_falso&amp;#039;: forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true -&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] H.&lt;br /&gt;
  -                  (* H : true &amp;lt;&amp;gt; true&lt;br /&gt;
                        ============================&lt;br /&gt;
                        true = false *)&lt;br /&gt;
    unfold not in H. (* H : true = true -&amp;gt; False&lt;br /&gt;
                        ============================&lt;br /&gt;
                        true = false *)&lt;br /&gt;
    exfalso.         (* H : true = true -&amp;gt; False&lt;br /&gt;
                        ============================&lt;br /&gt;
                        False *)&lt;br /&gt;
    apply H.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                  (* H : false &amp;lt;&amp;gt; true&lt;br /&gt;
                        ============================&lt;br /&gt;
                        false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas. &lt;br /&gt;
   1. Uso de &amp;#039;apply ex_falso_quodlibet&amp;#039; en la primera demostración.&lt;br /&gt;
   2. Uso de &amp;#039;exfalso&amp;#039; en la segunda demostración.&lt;br /&gt;
   3. La táctica &amp;#039;exfalso&amp;#039; sustituye el objetivo por falso. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.4. Verdad&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.1. Demostrar que la proposición True es verdadera.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma True_es_verdadera : True.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply I.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso del constructor I.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.5. Equivalencia lógica  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module DefIff.&lt;br /&gt;
&lt;br /&gt;
  (* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.1. Definir la función&lt;br /&gt;
      iff (P Q : Prop) : Prop&lt;br /&gt;
   tal que  (iff P Q) es la equivalencia de P y Q.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Definition iff (P Q : Prop) : Prop := (P -&amp;gt; Q) /\ (Q -&amp;gt; P).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.2. Definir (P &amp;lt;-&amp;gt; Q) como una abreviatura de (iff P Q). &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;P &amp;lt;-&amp;gt; Q&amp;quot; := (iff P Q)&lt;br /&gt;
                      (at level 95, no associativity)&lt;br /&gt;
                      : type_scope.&lt;br /&gt;
&lt;br /&gt;
End DefIff.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.3. Demostrar que&lt;br /&gt;
      forall P Q : Prop,&lt;br /&gt;
        (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iff_sim : forall P Q : Prop,&lt;br /&gt;
  (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; P).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q [HPQ HQP]. (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q &amp;lt;-&amp;gt; P *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           Q -&amp;gt; P *)&lt;br /&gt;
    apply HQP.&lt;br /&gt;
  -                     (* P, Q : Prop&lt;br /&gt;
                           HPQ : P -&amp;gt; Q&lt;br /&gt;
                           HQP : Q -&amp;gt; P&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; Q *)&lt;br /&gt;
    apply HPQ.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.4. Demostrar que&lt;br /&gt;
      forall b : bool,&lt;br /&gt;
        b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma not_true_iff_false : forall b : bool,&lt;br /&gt;
  b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.                      (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true &amp;lt;-&amp;gt; b = false *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                              (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true -&amp;gt; b = false *)&lt;br /&gt;
    apply no_verdadero_es_falso. &lt;br /&gt;
  -                              (* b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b = false -&amp;gt; b &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H.                    (* b : bool&lt;br /&gt;
                                    H : b = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    b &amp;lt;&amp;gt; true *)&lt;br /&gt;
    rewrite H.                   (* false &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H&amp;#039;.                   (* b : bool&lt;br /&gt;
                                    H : b = false&lt;br /&gt;
                                    H&amp;#039; : false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    False *)&lt;br /&gt;
    inversion H&amp;#039;.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.4. Demostrar que&lt;br /&gt;
      forall P : Prop,&lt;br /&gt;
        P &amp;lt;-&amp;gt; P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma iff_refl_aux: forall P : Prop,&lt;br /&gt;
    P -&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P H. (* P : Prop&lt;br /&gt;
                 H : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem iff_refl: forall P : Prop,&lt;br /&gt;
    P &amp;lt;-&amp;gt; P.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                     (* P : Prop&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; P *)&lt;br /&gt;
    apply iff_refl_aux. &lt;br /&gt;
  -                     (* P : Prop&lt;br /&gt;
                           ============================&lt;br /&gt;
                           P -&amp;gt; P *)&lt;br /&gt;
    apply iff_refl_aux.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.5. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; R) -&amp;gt; (P &amp;lt;-&amp;gt; R).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iff_trans: forall P Q R : Prop,&lt;br /&gt;
  (P &amp;lt;-&amp;gt; Q) -&amp;gt; (Q &amp;lt;-&amp;gt; R) -&amp;gt; (P &amp;lt;-&amp;gt; R).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R [HPQ HQP] [HQR HRQ]. (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P &amp;lt;-&amp;gt; R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                                 (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P -&amp;gt; R *)&lt;br /&gt;
    intros HP.                      (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       HP : P&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       R *)&lt;br /&gt;
    apply HQR.                      (* Q *)&lt;br /&gt;
    apply HPQ.                      (* P *)&lt;br /&gt;
    apply HP.&lt;br /&gt;
  -                                 (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       R -&amp;gt; P *)&lt;br /&gt;
    intros HR.                      (* P, Q, R : Prop&lt;br /&gt;
                                       HPQ : P -&amp;gt; Q&lt;br /&gt;
                                       HQP : Q -&amp;gt; P&lt;br /&gt;
                                       HQR : Q -&amp;gt; R&lt;br /&gt;
                                       HRQ : R -&amp;gt; Q&lt;br /&gt;
                                       HR : R&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       P *)&lt;br /&gt;
    apply HQP.                      (* Q *)&lt;br /&gt;
    apply HRQ.                      (* R *)&lt;br /&gt;
    apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.6. Demostrar que&lt;br /&gt;
      forall P Q R : Prop,&lt;br /&gt;
        P \/ (Q /\ R) &amp;lt;-&amp;gt; (P \/ Q) /\ (P \/ R).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem distributiva_disy_conj: forall P Q R : Prop,&lt;br /&gt;
  P \/ (Q /\ R) &amp;lt;-&amp;gt; (P \/ Q) /\ (P \/ R).&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                             (* P, Q, R : Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) -&amp;gt; (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
    intros [HP | [HQ HR]].&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ Q *)&lt;br /&gt;
        left.                   (* P *)&lt;br /&gt;
        apply HP.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HP : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ R *)&lt;br /&gt;
        left.                   (* P *)&lt;br /&gt;
        apply HP.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ Q *)&lt;br /&gt;
        right.                  (* Q *)&lt;br /&gt;
        apply HQ.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ R *)&lt;br /&gt;
        right.                  (* R *)&lt;br /&gt;
        apply HR.&lt;br /&gt;
  -                             (* P, Q, R : Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (P \/ Q) /\ (P \/ R) -&amp;gt; P \/ (Q /\ R) *)&lt;br /&gt;
    intros [[HP1|HQ] [HP2|HR]]. &lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP1, HP2 : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP1.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HP1 : P&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP1.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HP2 : P&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      left.                     (* P *)&lt;br /&gt;
      apply HP2.&lt;br /&gt;
    +                           (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P \/ (Q /\ R) *)&lt;br /&gt;
      right.                    (* Q /\ R *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Q *)&lt;br /&gt;
        apply HQ.&lt;br /&gt;
      *                         (* P, Q, R : Prop&lt;br /&gt;
                                   HQ : Q&lt;br /&gt;
                                   HR : R&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   R *)&lt;br /&gt;
        apply HR.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Se importa la librería Coq.Setoids.Setoid para usar las&lt;br /&gt;
   tácticas reflexivity y rewrite con iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Require Import Coq.Setoids.Setoid.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.5. Demostrar que&lt;br /&gt;
      forall n m : nat, n * m = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_0 : forall n m : nat, n * m = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                  (* n, m : nat&lt;br /&gt;
                        ============================&lt;br /&gt;
                        n * m = 0 -&amp;gt; n = 0 \/ m = 0 *)&lt;br /&gt;
    apply mult_eq_0. &lt;br /&gt;
  -                  (* n, m : nat&lt;br /&gt;
                        ============================&lt;br /&gt;
                        n = 0 \/ m = 0 -&amp;gt; n * m = 0 *)&lt;br /&gt;
    apply disy_ej.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.6. Demostrar que&lt;br /&gt;
      forall P Q R : Prop, &lt;br /&gt;
        P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma disy_asociativa :&lt;br /&gt;
  forall P Q R : Prop, P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P Q R.           (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) &amp;lt;-&amp;gt; (P \/ Q) \/ R *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                       (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) -&amp;gt; (P \/ Q) \/ R *)&lt;br /&gt;
    intros [H | [H | H]]. &lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P \/ Q *)&lt;br /&gt;
      left.               (* P *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : Q&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P \/ Q *)&lt;br /&gt;
      right.              (* Q *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : R&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      right.              (* R *)&lt;br /&gt;
      apply H.&lt;br /&gt;
  -                       (* P, Q, R : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R -&amp;gt; P \/ (Q \/ R) *)&lt;br /&gt;
    intros [[H | H] | H].&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (P \/ Q) \/ R *)&lt;br /&gt;
      left.               (* P *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : Q&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) *)&lt;br /&gt;
      right.              (* Q \/ R *)&lt;br /&gt;
      left.               (* Q *)&lt;br /&gt;
      apply H.&lt;br /&gt;
    +                     (* P, Q, R : Prop&lt;br /&gt;
                             H : R&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ (Q \/ R) *)&lt;br /&gt;
      right.              (* Q \/ R *)&lt;br /&gt;
      right.              (* R *)&lt;br /&gt;
      apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.7. Demostrar que&lt;br /&gt;
      forall n m p : nat,&lt;br /&gt;
        n * m * p = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0 \/ p = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma mult_0_3: forall n m p : nat,&lt;br /&gt;
    n * m * p = 0 &amp;lt;-&amp;gt; n = 0 \/ m = 0 \/ p = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.            (* n, m, p : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              n * (m * p) = 0 &amp;lt;-&amp;gt; n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite mult_0.          (* n * m = 0 \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite mult_0.          (* (n = 0 \/ m = 0) \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              n = 0 \/ (m = 0 \/ p = 0) *)&lt;br /&gt;
  rewrite disy_asociativa. (* (n = 0 \/ m = 0) \/ p = 0 &amp;lt;-&amp;gt; &lt;br /&gt;
                              (n = 0 \/ m = 0) \/ p = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de reflexivity y rewrite con iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.8. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma ej_apply_iff: forall n m : nat,&lt;br /&gt;
    n * m = 0 -&amp;gt; n = 0 \/ m = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : n * m = 0&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = 0 \/ m = 0 *)&lt;br /&gt;
  apply mult_0. (* n * m = 0 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de apply sobre iff.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.6. Cuantificación existencial  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.1. Demostrar que&lt;br /&gt;
      exists n : nat, 4 = n + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuatro_es_par: exists n : nat, 4 = n + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  exists 2.          (* &lt;br /&gt;
                   ============================&lt;br /&gt;
                   4 = 2 + 2 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La táctica &amp;#039;exists a&amp;#039; sustituye el objetivo de la forma &lt;br /&gt;
   (exists x, P(x)) por P(a).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(** Conversely, if we have an existential hypothesis [exists x, P] in&lt;br /&gt;
    the context, we can destruct it to obtain a witness [x] and a&lt;br /&gt;
    hypothesis stating that [P] holds of [x]. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.2. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        (exists m, n = 4 + m) -&amp;gt; (exists o, n = 2 + o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem ej_existe_2a: forall n : nat,&lt;br /&gt;
  (exists m, n = 4 + m) -&amp;gt;&lt;br /&gt;
  (exists o, n = 2 + o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.&lt;br /&gt;
  destruct H as [a Ha].&lt;br /&gt;
  exists (2 + a).&lt;br /&gt;
  apply Ha.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem ej_existe_2b: forall n : nat,&lt;br /&gt;
  (exists m, n = 4 + m) -&amp;gt;&lt;br /&gt;
  (exists o, n = 2 + o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n [a Ha]. &lt;br /&gt;
  exists (2 + a).&lt;br /&gt;
  apply Ha.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. &amp;#039;destruct H [a Ha]&amp;#039; sustituye la hipótesis (H : exists x, P(x)) &lt;br /&gt;
      por (Ha : P(a)).&lt;br /&gt;
   2. &amp;#039;intros x [a Ha]&amp;#039; sustituye el objetivo &lt;br /&gt;
      (forall x, (exists y P(y)) -&amp;gt; Q(x)) por Q(x) y le añade la&lt;br /&gt;
      hipótesis (Ha : P(a)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.1. Demostrar que&lt;br /&gt;
      forall (X:Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
        (forall x, P x) -&amp;gt; ~ (exists x, ~ P x)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem paraTodo_no_existe_no: forall (X:Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
  (forall x, P x) -&amp;gt; ~ (exists x, ~ P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X P H1 [a Ha]. (* X : Type&lt;br /&gt;
                           P : X -&amp;gt; Prop&lt;br /&gt;
                           H1 : forall x : X, P x&lt;br /&gt;
                           a : X&lt;br /&gt;
                           Ha : ~ P a&lt;br /&gt;
                           ============================&lt;br /&gt;
                           False *)&lt;br /&gt;
  apply Ha.             (* P a *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (P Q : X -&amp;gt; Prop),&lt;br /&gt;
        (exists x, P x \/ Q x) &amp;lt;-&amp;gt; (exists x, P x) \/ (exists x, Q x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem dist_existe: forall (X : Type) (P Q : X -&amp;gt; Prop),&lt;br /&gt;
  (exists x, P x \/ Q x) &amp;lt;-&amp;gt; (exists x, P x) \/ (exists x, Q x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X P Q.                 (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x \/ Q x) &amp;lt;-&amp;gt; &lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x : X, P x \/ Q x) -&amp;gt; &lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
    intros [a [HPa | HQa]].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HPa : P a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
      left.                     (* exists x : X, P x *)&lt;br /&gt;
      exists a.                      (* P a *)&lt;br /&gt;
      apply HPa.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HQa : Q a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) *)&lt;br /&gt;
      right.                    (* exists x : X, Q x *)&lt;br /&gt;
      exists a.                      (* Q a *)&lt;br /&gt;
      apply HQa.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (exists x:X, P x) \/ (exists x:X, Q x) -&amp;gt; &lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
    intros [[a HPa] | [a HQa]]. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HPa : P a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
      exists a.                      (* P a \/ Q a *)&lt;br /&gt;
      left.                     (* P a *)&lt;br /&gt;
      apply HPa.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   P, Q : X -&amp;gt; Prop&lt;br /&gt;
                                   a : X&lt;br /&gt;
                                   HQa : Q a&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   exists x : X, P x \/ Q x *)&lt;br /&gt;
      exists a.                      (* P a \/ Q a *)&lt;br /&gt;
      right.                    (* Q a *)&lt;br /&gt;
      apply HQa.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Programación con proposiciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.1. Definir la función&lt;br /&gt;
      En {A : Type} (x : A) (xs : list A) : Prop :=&lt;br /&gt;
   tal que (En x xs) se verifica si x pertenece a xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint En {A : Type} (x : A) (xs : list A) : Prop :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []        =&amp;gt; False&lt;br /&gt;
  | x&amp;#039; :: xs&amp;#039; =&amp;gt; x&amp;#039; = x \/ En x xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.2. Demostrar que&lt;br /&gt;
      En 4 [1; 2; 3; 4; 5].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example En_ejemplo_1 : En 4 [1; 2; 3; 4; 5].&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* 1 = 4 \/ 2 = 4 \/ 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 2 = 4 \/ 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 3 = 4 \/ 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  right.       (* 4 = 4 \/ 5 = 4 \/ False *)&lt;br /&gt;
  left.        (* 4 = 4 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.3. Demostrar que&lt;br /&gt;
      forall n : nat, &lt;br /&gt;
        En n [2; 4] -&amp;gt; exists n&amp;#039;, n = 2 * n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example En_ejemplo_2: forall n : nat,&lt;br /&gt;
    En n [2; 4] -&amp;gt; exists n&amp;#039;, n = 2 * n&amp;#039;.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.                   (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              forall n : nat,&lt;br /&gt;
                               2 = n \/ 4 = n \/ False -&amp;gt; &lt;br /&gt;
                               exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
  intros n [H | [H | []]]. &lt;br /&gt;
  -                        (* n : nat&lt;br /&gt;
                              H : 2 = n&lt;br /&gt;
                              ============================&lt;br /&gt;
                              exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
    exists 1.                   (* n = 1 + (1 + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- H.           (* 2 = 1 + (1 + 0) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* n : nat&lt;br /&gt;
                              H : 4 = n&lt;br /&gt;
                              ============================&lt;br /&gt;
                              exists n&amp;#039; : nat, n = n&amp;#039; + (n&amp;#039; + 0) *)&lt;br /&gt;
    exists 2.                   (* n = 2 + (2 + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- H.           (* 4 = 2 + (2 + 0) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso del patrón vacóp para descartar el último caso.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (x : A),&lt;br /&gt;
        En x xs -&amp;gt;&lt;br /&gt;
        En (f x) (map f xs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lemma En_map: forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (x : A),&lt;br /&gt;
    En x xs -&amp;gt;&lt;br /&gt;
    En (f x) (map f xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f xs x.            (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   xs : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x xs -&amp;gt; En (f x) (map f xs) *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x [ ] -&amp;gt; En (f x) (map f [ ]) *)&lt;br /&gt;
    simpl.                      (* False -&amp;gt; False *)&lt;br /&gt;
    intros [].&lt;br /&gt;
  -                             (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x (x&amp;#039;::xs&amp;#039;) -&amp;gt; &lt;br /&gt;
                                   En (f x) (map f (x&amp;#039;::xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                      (* x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
    intros [H | H].&lt;br /&gt;
    +                           (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   H : x&amp;#039; = x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      rewrite H.                (* f x = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      left.                     (* f x = f x *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* A : Type&lt;br /&gt;
                                   B : Type&lt;br /&gt;
                                   f : A -&amp;gt; B&lt;br /&gt;
                                   x&amp;#039; : A&lt;br /&gt;
                                   xs&amp;#039; : list A&lt;br /&gt;
                                   x : A&lt;br /&gt;
                                   HI : En x xs&amp;#039; -&amp;gt; En (f x) (map f xs&amp;#039;)&lt;br /&gt;
                                   H : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   f x&amp;#039; = f x \/ En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      right.                    (* En (f x) (map f xs&amp;#039;) *)&lt;br /&gt;
      apply HI.                 (* En x xs&amp;#039; *)&lt;br /&gt;
      apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (y : B),&lt;br /&gt;
        En y (map f xs) &amp;lt;-&amp;gt;&lt;br /&gt;
        exists x, f x = y /\ En x xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma En_map_iff: forall (A B : Type) (f : A -&amp;gt; B) (xs : list A) (y : B),&lt;br /&gt;
    En y (map f xs) &amp;lt;-&amp;gt;&lt;br /&gt;
    exists x, f x = y /\ En x xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f xs y.                  (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         xs : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f xs) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x xs) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                                   (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f [ ]) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x [ ]) *)&lt;br /&gt;
    simpl.                            (* En y (map f [ ]) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x [ ]) *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         False -&amp;gt; &lt;br /&gt;
                                         exists x : A, f x = y /\ False *)&lt;br /&gt;
      intros [].&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         (exists x : A, f x = y /\ False) -&amp;gt; &lt;br /&gt;
                                         False *)&lt;br /&gt;
      intros [a [H []]].&lt;br /&gt;
  -                                   (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En y (map f (x :: xs&amp;#039;)) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                           f x0 = y /\ En x0 (x :: xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                            (* f x = y \/ En y (map f xs&amp;#039;) &amp;lt;-&amp;gt;&lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                           f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;)) *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) -&amp;gt;&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
      intros [H1 | H2].&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        exists x.                        (* f x = y /\ (x = x \/ En x xs&amp;#039;) *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y *)&lt;br /&gt;
          apply H1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H1 : f x = y&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         x = x \/ En x xs&amp;#039; *)&lt;br /&gt;
          left.                       (* x = x *)&lt;br /&gt;
          reflexivity.&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H2 : En y (map f xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        apply HI in H2.               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         H2 : exists x : A, f x = y /\ En x xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        destruct H2 as [a [Ha1 Ha2]]. (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;) *)&lt;br /&gt;
        &lt;br /&gt;
        exists a.                          (* En y (map f xs) &amp;lt;-&amp;gt; &lt;br /&gt;
                                         (exists x : A, f x = y /\ En x xs) *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f a = y *)&lt;br /&gt;
          apply Ha1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         x = a \/ En a xs&amp;#039; *)&lt;br /&gt;
          right.                      (* En a xs&amp;#039; *)&lt;br /&gt;
          apply Ha2.&lt;br /&gt;
    +                                 (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x : A, &lt;br /&gt;
                                                f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         (exists x0 : A, &lt;br /&gt;
                                          f x0 = y /\ (x = x0 \/ En x0 xs&amp;#039;)) -&amp;gt;&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
      intros [a [Ha1 [Ha2 | Ha3]]].&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha2 : x = a&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
        left.                         (* f x = y *)&lt;br /&gt;
        rewrite Ha2.                  (* f a = y *)&lt;br /&gt;
        rewrite Ha1.                  (* y = y *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                               (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f x = y \/ En y (map f xs&amp;#039;) *)&lt;br /&gt;
        right.                        (* En y (map f xs&amp;#039;) *)&lt;br /&gt;
        apply HI.                     (* exists x0 : A, f x0 = y /\ En x0 xs&amp;#039; *)&lt;br /&gt;
        exists a.                          (* f a = y /\ En a xs&amp;#039; *)&lt;br /&gt;
        split.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         f a = y *)&lt;br /&gt;
          apply Ha1.&lt;br /&gt;
        --                            (* A : Type&lt;br /&gt;
                                         B : Type&lt;br /&gt;
                                         f : A -&amp;gt; B&lt;br /&gt;
                                         x : A&lt;br /&gt;
                                         xs&amp;#039; : list A&lt;br /&gt;
                                         y : B&lt;br /&gt;
                                         HI : En y (map f xs&amp;#039;) &amp;lt;-&amp;gt; &lt;br /&gt;
                                              (exists x:A, f x = y /\ En x xs&amp;#039;)&lt;br /&gt;
                                         a : A&lt;br /&gt;
                                         Ha1 : f a = y&lt;br /&gt;
                                         Ha3 : En a xs&amp;#039;&lt;br /&gt;
                                         ============================&lt;br /&gt;
                                         En a xs&amp;#039; *)&lt;br /&gt;
          apply Ha3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall A (xs ys : list A) (a : A),&lt;br /&gt;
        En a (xs ++ ys) &amp;lt;-&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma En_conc_1: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a (xs ++ ys) -&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].    &lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a ([ ] ++ ys) -&amp;gt; En a [ ] \/ En a ys *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a ys -&amp;gt; False \/ En a ys *)&lt;br /&gt;
    intros ys a H.                (* A : Type&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     False \/ En a ys *)&lt;br /&gt;
    right.                        (* En a ys *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A),&lt;br /&gt;
                                      En a ((x :: xs&amp;#039;) ++ ys) -&amp;gt; &lt;br /&gt;
                                      En a (x :: xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A),&lt;br /&gt;
                                      x = a \/ En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                      (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
    intros ys a [H1 | H2].&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H1 : x = a&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
      left.                       (* x = a \/ En a xs&amp;#039; *)&lt;br /&gt;
      left.                       (* x = a *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys) -&amp;gt; &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H2 : En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     (x = a \/ En a xs&amp;#039;) \/ En a ys *)&lt;br /&gt;
      rewrite &amp;lt;- disy_asociativa.  (* x = a \/ (En a xs&amp;#039; \/ En a ys) *)&lt;br /&gt;
      right.                      (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      apply HI.                   (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma En_conc_2: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a xs \/ En a ys -&amp;gt; En a (xs ++ ys). &lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A), &lt;br /&gt;
                                      En a [ ] \/ En a ys -&amp;gt; En a ([ ] ++ ys) *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A), &lt;br /&gt;
                                      False \/ En a ys -&amp;gt; En a ys *)&lt;br /&gt;
    intros ys a [[] | H].         (* A : Type&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a ys *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                               (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall (ys : list A) (a : A),&lt;br /&gt;
                                      En a (x :: xs&amp;#039;) \/ En a ys -&amp;gt; &lt;br /&gt;
                                      En a ((x :: xs&amp;#039;) ++ ys) *)&lt;br /&gt;
    simpl.                        (* forall (ys : list A) (a : A),&lt;br /&gt;
                                      (x = a \/ En a xs&amp;#039;) \/ En a ys -&amp;gt; &lt;br /&gt;
                                      x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
    intros ys a [[H1 | H2] | H3]. &lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H1 : x = a&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      left.                       (* x = a *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H2 : En a xs&amp;#039;&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      right.                      (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply HI.                   (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      left.                       (* En a xs&amp;#039; *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
    +                             (* A : Type&lt;br /&gt;
                                     x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HI : forall (ys : list A) (a : A), &lt;br /&gt;
                                           En a xs&amp;#039; \/ En a ys -&amp;gt; &lt;br /&gt;
                                           En a (xs&amp;#039; ++ ys)&lt;br /&gt;
                                     ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     H3 : En a ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x = a \/ En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      right.                      (* En a (xs&amp;#039; ++ ys) *)&lt;br /&gt;
      apply HI.                   (* En a xs&amp;#039; \/ En a ys *)&lt;br /&gt;
      right.                      (* En a ys *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
Lemma En_conc: forall A (xs ys : list A) (a : A),&lt;br /&gt;
  En a (xs ++ ys) &amp;lt;-&amp;gt; En a xs \/ En a ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                  (* A : Type&lt;br /&gt;
                        xs, ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a (xs ++ ys) -&amp;gt; En a xs \/ En a ys *)&lt;br /&gt;
    apply En_conc_1. &lt;br /&gt;
  -                  (* A : Type&lt;br /&gt;
                                     xs, ys : list A&lt;br /&gt;
                                     a : A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     En a xs \/ En a ys -&amp;gt; En a (xs ++ ys) *)&lt;br /&gt;
    apply En_conc_2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3.1. Definir la propiedad&lt;br /&gt;
      Todos {T : Type} (P : T -&amp;gt; Prop) (xs : list T) : Prop&lt;br /&gt;
   tal que (Todos P xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   la propiedad P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint Todos {T : Type} (P : T -&amp;gt; Prop) (xs : list T) : Prop :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; True&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; P x /\ Todos P xs&amp;#039; &lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3.2. Demostrar que&lt;br /&gt;
      forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
        (forall x, En x xs -&amp;gt; P x) &amp;lt;-&amp;gt;&lt;br /&gt;
        Todos P xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En_1: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x) -&amp;gt;&lt;br /&gt;
    Todos P xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].  &lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (forall x : T, En x [ ] -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                   Todos P [ ] *) &lt;br /&gt;
    simpl.                      (* (forall x : T, False -&amp;gt; P x) -&amp;gt; True *)&lt;br /&gt;
    intros.                     (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   H : forall x : T, False -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   True *)&lt;br /&gt;
    apply I.&lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (forall x : T, En x (x&amp;#039; :: xs&amp;#039;) -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                   Todos P (x&amp;#039; :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* (forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x) -&amp;gt;&lt;br /&gt;
                                   P x&amp;#039; /\ Todos P xs&amp;#039; *)&lt;br /&gt;
    intros H.                   (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x&amp;#039; /\ Todos P xs&amp;#039; *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x&amp;#039; *)&lt;br /&gt;
      apply H.                  (* x&amp;#039; = x&amp;#039; \/ En x&amp;#039; xs&amp;#039; *)&lt;br /&gt;
      left.                     (* x&amp;#039; = x&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P xs&amp;#039; *)&lt;br /&gt;
      apply HI.                 (* forall x : T, En x xs&amp;#039; -&amp;gt; P x *)&lt;br /&gt;
      intros x H1.              (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : (forall x : T, En x xs&amp;#039; -&amp;gt; P x) -&amp;gt; &lt;br /&gt;
                                        Todos P xs&amp;#039;&lt;br /&gt;
                                   H : forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H1 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      apply H.                  (* x&amp;#039; = x \/ En x xs&amp;#039; *)&lt;br /&gt;
      right.                    (* En x xs&amp;#039; *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En_2: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    Todos P xs -&amp;gt;&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P [ ] -&amp;gt; &lt;br /&gt;
                                   forall x : T, En x [ ] -&amp;gt; P x *)&lt;br /&gt;
    simpl.                      (* True -&amp;gt; forall x : T, False -&amp;gt; P x *)&lt;br /&gt;
    intros [].                  (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall x : T, False -&amp;gt; P x *)&lt;br /&gt;
    intros x [].&lt;br /&gt;
  -                             (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P (x&amp;#039; :: xs&amp;#039;) -&amp;gt; &lt;br /&gt;
                                   forall x : T, En x (x&amp;#039; :: xs&amp;#039;) -&amp;gt; P x *)&lt;br /&gt;
    simpl.                      (* P x&amp;#039; /\ Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                   forall x : T, x&amp;#039; = x \/ En x xs&amp;#039; -&amp;gt; P x *)&lt;br /&gt;
    intros [H1 H2] x [H3 | H4]. &lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H3 : x&amp;#039; = x&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      rewrite &amp;lt;- H3.             (* P x&amp;#039; *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                           (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   P x *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
      *                         (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos P xs&amp;#039; *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
      *                         (* T : Type&lt;br /&gt;
                                   P : T -&amp;gt; Prop&lt;br /&gt;
                                   x&amp;#039; : T&lt;br /&gt;
                                   xs&amp;#039; : list T&lt;br /&gt;
                                   HI : Todos P xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        forall x : T, En x xs&amp;#039; -&amp;gt; P x&lt;br /&gt;
                                   H1 : P x&amp;#039;&lt;br /&gt;
                                   H2 : Todos P xs&amp;#039;&lt;br /&gt;
                                   x : T&lt;br /&gt;
                                   H4 : En x xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   En x xs&amp;#039; *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma Todos_En: &lt;br /&gt;
  forall T (P : T -&amp;gt; Prop) (xs : list T),&lt;br /&gt;
    (forall x, En x xs -&amp;gt; P x) &amp;lt;-&amp;gt;&lt;br /&gt;
    Todos P xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                   (* T : Type&lt;br /&gt;
                         P : T -&amp;gt; Prop&lt;br /&gt;
                         xs : list T&lt;br /&gt;
                         ============================&lt;br /&gt;
                         (forall x : T, En x xs -&amp;gt; P x) -&amp;gt; Todos P xs *)&lt;br /&gt;
    apply Todos_En_1. &lt;br /&gt;
  -                   (* T : Type&lt;br /&gt;
                         P : T -&amp;gt; Prop&lt;br /&gt;
                         xs : list T&lt;br /&gt;
                         ============================&lt;br /&gt;
                         Todos P xs -&amp;gt; forall x : T, En x xs -&amp;gt; P x *)&lt;br /&gt;
    apply Todos_En_2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.1. Definir la propiedad&lt;br /&gt;
      combina_par_impar (Pimpar Ppar : nat -&amp;gt; Prop) : nat -&amp;gt; Prop&lt;br /&gt;
   tal que (combina_par_impar Pimpar Ppar) es una función que asigna a n&lt;br /&gt;
   (Pimpar n) si n es impar y (Ppar n) si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition combina_par_impar (Pimpar Ppar : nat -&amp;gt; Prop) : nat -&amp;gt; Prop :=&lt;br /&gt;
  fun n =&amp;gt; (esImpar n = true -&amp;gt; Pimpar n) /\&lt;br /&gt;
        (esImpar n = false -&amp;gt; Ppar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.2. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        (esImpar n = true -&amp;gt; Pimpar n) -&amp;gt;&lt;br /&gt;
        (esImpar n = false -&amp;gt; Ppar n) -&amp;gt;&lt;br /&gt;
        combina_par_impar Pimpar Ppar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_intro :&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    (esImpar n = true -&amp;gt; Pimpar n) -&amp;gt;&lt;br /&gt;
    (esImpar n = false -&amp;gt; Ppar n) -&amp;gt;&lt;br /&gt;
    combina_par_impar Pimpar Ppar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Par n H1 H2. (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                combina_par_impar Pimpar Par n *)&lt;br /&gt;
  unfold combina_par_impar.  (* (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                (esImpar n = false -&amp;gt; Par n) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                          (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                esImpar n = true -&amp;gt; Pimpar n *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* Pimpar, Par : nat -&amp;gt; Prop&lt;br /&gt;
                                n : nat&lt;br /&gt;
                                H1 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                H2 : esImpar n = false -&amp;gt; Par n&lt;br /&gt;
                                ============================&lt;br /&gt;
                                esImpar n = false -&amp;gt; Par n *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.3. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
        esImpar n = true -&amp;gt;&lt;br /&gt;
        Pimpar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_elim_impar:&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
    esImpar n = true -&amp;gt;&lt;br /&gt;
    Pimpar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Ppar n H1 H2.     (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : combina_par_impar Pimpar Ppar n&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                    Pimpar n *)&lt;br /&gt;
  unfold combina_par_impar in H1. (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                          (esImpar n = false -&amp;gt; Ppar n)&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Pimpar n *)&lt;br /&gt;
  destruct H1 as [H3 H4].         (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H3 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                     H4 : esImpar n = false -&amp;gt; Ppar n&lt;br /&gt;
                                     H2 : esImpar n = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Pimpar n *)&lt;br /&gt;
  apply H3.                       (* esImpar n = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.4. Demostrar que&lt;br /&gt;
      forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
        combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
        esImpar n = false -&amp;gt;&lt;br /&gt;
        Ppar n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem combina_par_impar_elim_par:&lt;br /&gt;
  forall (Pimpar Ppar : nat -&amp;gt; Prop) (n : nat),&lt;br /&gt;
    combina_par_impar Pimpar Ppar n -&amp;gt;&lt;br /&gt;
    esImpar n = false -&amp;gt;&lt;br /&gt;
    Ppar n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros Pimpar Ppar n H1 H2.     (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : combina_par_impar Pimpar Ppar n&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  unfold combina_par_impar in H1. (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H1 : (esImpar n = true -&amp;gt; Pimpar n) /\ &lt;br /&gt;
                                          (esImpar n = false -&amp;gt; Ppar n)&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  destruct H1 as [H3 H4].         (* Pimpar, Ppar : nat -&amp;gt; Prop&lt;br /&gt;
                                     n : nat&lt;br /&gt;
                                     H3 : esImpar n = true -&amp;gt; Pimpar n&lt;br /&gt;
                                     H4 : esImpar n = false -&amp;gt; Ppar n&lt;br /&gt;
                                     H2 : esImpar n = false&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     Ppar n *)&lt;br /&gt;
  apply H4.                       (* esImpar n = false *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Aplicando teoremas a argumentos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Evaluar la expresión&lt;br /&gt;
      Check suma_conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check suma_conmutativa.&lt;br /&gt;
(* ===&amp;gt; forall n m : nat, n + m = m + n *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En Coq, las demostraciones son objetos de primera clase.&lt;br /&gt;
   2. Coq devuelve el tipo de suma_conmutativa como es de cualquier&lt;br /&gt;
      expresión.&lt;br /&gt;
   3. El identificador suma_conmutativa representa un objeto prueba de&lt;br /&gt;
      (forall n m : nat, n + m = m + n).&lt;br /&gt;
   4. Un término de tipo (nat -&amp;gt; nat -&amp;gt; nat) transforma dos naturales en&lt;br /&gt;
      un natural.&lt;br /&gt;
   5. Análogamente, un término de tipo (n = m -&amp;gt; n + n = m + m)&lt;br /&gt;
      transforma un argumento de tipo (n = m) en otro de tipo &lt;br /&gt;
      (n + n = m + m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(** Operationally, this analogy goes even further: by applying a&lt;br /&gt;
    theorem, as if it were a function, to hypotheses with matching&lt;br /&gt;
    types, we can specialize its result without having to resort to&lt;br /&gt;
    intermediate assertions.  For example, suppose we wanted to prove&lt;br /&gt;
    the following result: *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.2. Demostrar que&lt;br /&gt;
      forall x y z : nat, &lt;br /&gt;
        x + (y + z) = (z + y) + x.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Lemma suma_conmutativa3a :&lt;br /&gt;
  forall x y z : nat,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.             (* x, y, z : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               x + (y + z) = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa. (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa. (* x + (y + z) = (z + y) + x *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Lemma suma_conmutativa3b :&lt;br /&gt;
  forall x y z,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.               (* x, y, z : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x + (y + z) = z + y + x *)&lt;br /&gt;
  rewrite suma_conmutativa.   (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  assert (H : y + z = z + y). &lt;br /&gt;
  -                           (* x, y, z : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 y + z = z + y *)&lt;br /&gt;
    rewrite suma_conmutativa. (* z + y = z + y *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* x, y, z : nat&lt;br /&gt;
                                 H : y + z = z + y&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (y + z) + x = (z + y) + x *)&lt;br /&gt;
    rewrite H.                (* (z + y) + x = (z + y) + x *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 3º intento *)&lt;br /&gt;
Lemma suma_conmutativa3c:&lt;br /&gt;
  forall x y z,&lt;br /&gt;
    x + (y + z) = (z + y) + x.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y z.                   (* x, y, z : nat&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     x + (y + z) = (z + y) + x *)&lt;br /&gt;
  rewrite suma_conmutativa.       (* (y + z) + x = (z + y) + x *)&lt;br /&gt;
  rewrite (suma_conmutativa y z). (* (z + y) + x = (z + y) + x *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Indicación en (rewrite (suma_conmutativa y z)) de los&lt;br /&gt;
   argumentos con los que se aplica, análogamente a las funciones&lt;br /&gt;
   polimórficas. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.3. Demostrar que&lt;br /&gt;
     forall {n : nat} {ns : list nat},&lt;br /&gt;
       En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
       n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Lema auxiliar *)&lt;br /&gt;
Lemma producto_n_0:&lt;br /&gt;
  forall n : nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              0 * 0 = 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                        (* n&amp;#039; : nat&lt;br /&gt;
                              HI : n&amp;#039; * 0 = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              S n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    simpl.                 (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ej_aplicacion_de_lema_1:&lt;br /&gt;
  forall {n : nat} {ns : list nat},&lt;br /&gt;
    En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
    n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n ns H.              (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  rewrite En_map_iff in H.    (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 H : exists x : nat, x * 0 = n /\ En x ns&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  destruct H as [m [Hm _]].   (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 m : nat&lt;br /&gt;
                                 Hm : m * 0 = n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  rewrite producto_n_0 in Hm. (* n : nat&lt;br /&gt;
                                 ns : list nat&lt;br /&gt;
                                 m : nat&lt;br /&gt;
                                 Hm : 0 = n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = 0 *)&lt;br /&gt;
  symmetry.                   (* 0 = n *)&lt;br /&gt;
  apply Hm.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ej_aplicacion_de_lema:&lt;br /&gt;
  forall {n : nat} {ns : list nat},&lt;br /&gt;
    En n (map (fun m =&amp;gt; m * 0) ns) -&amp;gt;&lt;br /&gt;
    n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n ns H.                    (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  destruct (conj_e1 _ _&lt;br /&gt;
             (En_map_iff _ _ _ _ _) &lt;br /&gt;
             H)&lt;br /&gt;
           as [m [Hm _]].           (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       m : nat&lt;br /&gt;
                                       Hm : m * 0 = n&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  rewrite producto_n_0 in Hm.       (* n : nat&lt;br /&gt;
                                       ns : list nat&lt;br /&gt;
                                       H : En n (map (fun m : nat =&amp;gt; m * 0) ns)&lt;br /&gt;
                                       m : nat&lt;br /&gt;
                                       Hm : 0 = n&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n = 0 *)&lt;br /&gt;
  symmetry.                         (* 0 = n *)&lt;br /&gt;
  apply Hm.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Aplicación de teoremas a argumentos con&lt;br /&gt;
      (conj_e1 _ _  (En_map_iff _ _ _ _ _) H)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Coq vs. teoría de conjuntos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En lugar de decir que un elemento pertenece a un conjunto se puede&lt;br /&gt;
      decir que verifica la propiedad que define al conjunto.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.1. Extensionalidad funcional&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.1. Demostrar que&lt;br /&gt;
      plus 3 = plus (pred 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example igualdad_de_funciones_ej1:&lt;br /&gt;
  suma 3 = suma (pred 4).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.2. Definir el axioma de extensionalidad funcional que&lt;br /&gt;
   afirma que dos funciones son giuales cuando tienen los mismos&lt;br /&gt;
   valores. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Axiom extensionalidad_funcional : forall {X Y: Type}&lt;br /&gt;
                                    {f g : X -&amp;gt; Y},&lt;br /&gt;
  (forall (x:X), f x = g x) -&amp;gt; f = g.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.3. Demostrar que&lt;br /&gt;
      (fun x =&amp;gt; suma x 1) = (fun x =&amp;gt; suma 1 x).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example igualdad_de_funciones_ej2 :&lt;br /&gt;
  (fun x =&amp;gt; suma x 1) = (fun x =&amp;gt; suma 1 x).&lt;br /&gt;
Proof.&lt;br /&gt;
  apply extensionalidad_funcional. (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      forall x : nat, suma x 1 = suma 1 x *)&lt;br /&gt;
  intros x.                        (* x : nat&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      suma x 1 = suma 1 x *)&lt;br /&gt;
  apply suma_conmutativa.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. No se puede demostrar sin el axioma.&lt;br /&gt;
   2. Hay que ser cuidadoso en la definición de axiomas, porque se&lt;br /&gt;
      pueden introducir inconsistencias. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1.4. Calcular los axiomas usados en la prueba de &lt;br /&gt;
      igualdad_de_funciones_ej2&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Print Assumptions igualdad_de_funciones_ej2.&lt;br /&gt;
(* ===&amp;gt;&lt;br /&gt;
     Axioms:&lt;br /&gt;
     extensionalidad_funcional :&lt;br /&gt;
         forall (X Y : Type) (f g : X -&amp;gt; Y),&lt;br /&gt;
                (forall x : X, f x = g x) -&amp;gt; f = g *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1.1. Se considera la siguiente definición iterativa de la&lt;br /&gt;
   función inversa&lt;br /&gt;
      Fixpoint inversaIaux {X} (xs ys : list X) : list X :=&lt;br /&gt;
        match xs with&lt;br /&gt;
        | []       =&amp;gt; ys&lt;br /&gt;
        | x :: xs&amp;#039; =&amp;gt; inversaIaux xs&amp;#039; (x :: ys)&lt;br /&gt;
        end.&lt;br /&gt;
      &lt;br /&gt;
      Definition inversaI {X} (xs : list X) : list X :=&lt;br /&gt;
        inversaIaux xs [].&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall X : Type, &lt;br /&gt;
        @inversaI X = @inversa X.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint inversaIaux {X} (xs ys : list X) : list X :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []       =&amp;gt; ys&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; inversaIaux xs&amp;#039; (x :: ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Definition inversaI {X} (xs : list X) : list X :=&lt;br /&gt;
  inversaIaux xs [].&lt;br /&gt;
&lt;br /&gt;
Lemma inversaI_correcta_aux:&lt;br /&gt;
  forall (X : Type) (xs ys : list X),&lt;br /&gt;
    inversaIaux xs ys = inversa xs ++ ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux xs ys = inversa xs ++ ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].  &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux [ ] ys = inversa [ ] ++ ys *)&lt;br /&gt;
    simpl.                      (* forall ys : list X, ys = ys *)&lt;br /&gt;
    intros.                     (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   ys = ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : forall ys : list X, &lt;br /&gt;
                                         inversaIaux xs&amp;#039; ys = inversa xs&amp;#039; ++ ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X, &lt;br /&gt;
                                    inversaIaux (x :: xs&amp;#039;) ys = &lt;br /&gt;
                                    inversa (x :: xs&amp;#039;) ++ ys *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : forall ys : list X, &lt;br /&gt;
                                         inversaIaux xs&amp;#039; ys = inversa xs&amp;#039; ++ ys&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   inversaIaux (x :: xs&amp;#039;) ys = &lt;br /&gt;
                                   inversa (x :: xs&amp;#039;) ++ ys *)&lt;br /&gt;
    simpl.                      (* inversaIaux xs&amp;#039; (x :: ys) = &lt;br /&gt;
                                   (inversa xs&amp;#039; ++ [x]) ++ ys *)&lt;br /&gt;
    rewrite &amp;lt;- conc_asociativa.  (* inversaIaux xs&amp;#039; (x :: ys) = &lt;br /&gt;
                                   inversa xs&amp;#039; ++ ([x] ++ ys) *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
                                            &lt;br /&gt;
Lemma inversaI_correcta:&lt;br /&gt;
  forall X : Type,&lt;br /&gt;
    @inversaI X = @inversa X.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X.                        (* X : Type&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      inversaI = inversa *)&lt;br /&gt;
  apply extensionalidad_funcional. (* forall x : list X, &lt;br /&gt;
                                       inversaI x = inversa x *)&lt;br /&gt;
  intros.                          (* X : Type&lt;br /&gt;
                                      x : list X&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      inversaI x = inversa x *)&lt;br /&gt;
  unfold inversaI.                 (* inversaIaux x [ ] = inversa x *)&lt;br /&gt;
  rewrite inversaI_correcta_aux.   (* inversa x ++ [ ] = inversa x *)&lt;br /&gt;
  apply conc_nil.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.2. Proposiciones y booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.1. Demostrar que&lt;br /&gt;
     forall k : nat,&lt;br /&gt;
       esPar (doble k) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_doble:&lt;br /&gt;
  forall k : nat,&lt;br /&gt;
    esPar (doble k) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros k.                (* k : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble k) = true *)&lt;br /&gt;
  induction k as [|k&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble 0) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* k&amp;#039; : nat&lt;br /&gt;
                              HI : esPar (doble k&amp;#039;) = true&lt;br /&gt;
                              ============================&lt;br /&gt;
                              esPar (doble (S k&amp;#039;)) = true *)&lt;br /&gt;
    simpl.                 (* esPar (doble k&amp;#039;) = true *)&lt;br /&gt;
    apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.1. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        exists k : nat, n = if esPar n&lt;br /&gt;
                     then doble k&lt;br /&gt;
                     else S (doble k).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_doble_aux :&lt;br /&gt;
  forall n : nat,&lt;br /&gt;
    exists k : nat, n = if esPar n&lt;br /&gt;
                 then doble k&lt;br /&gt;
                 else S (doble k).&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HI].    &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   0 = (if esPar 0 &lt;br /&gt;
                                        then doble k &lt;br /&gt;
                                        else S (doble k)) *)&lt;br /&gt;
    exists 0.                       (* 0 = (if esPar 0 &lt;br /&gt;
                                       then doble 0 &lt;br /&gt;
                                       else S (doble 0)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* n&amp;#039; : nat&lt;br /&gt;
                                  HI : exists k : nat, &lt;br /&gt;
                                        n&amp;#039; = (if esPar n&amp;#039; &lt;br /&gt;
                                              then doble k &lt;br /&gt;
                                              else S (doble k))&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
    destruct (esPar n&amp;#039;) eqn:H. &lt;br /&gt;
    +                          (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = true&lt;br /&gt;
                                  HI : exists k : nat, n&amp;#039; = doble k&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite esPar_S.         (* exists k : nat,&lt;br /&gt;
                                   S n&amp;#039; = (if negacion (esPar n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite H.               (* exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if negacion true &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      simpl.                   (* exists k : nat, S n&amp;#039; = S (doble k) *)&lt;br /&gt;
      destruct HI as [k&amp;#039; Hk&amp;#039;]. (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = true&lt;br /&gt;
                                  k&amp;#039; : nat&lt;br /&gt;
                                  Hk&amp;#039; : n&amp;#039; = doble k&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, S n&amp;#039; = S (doble k) *)&lt;br /&gt;
      exists k&amp;#039;.                    (* S n&amp;#039; = S (doble k&amp;#039;) *)&lt;br /&gt;
      rewrite Hk&amp;#039;.             (* S (doble k&amp;#039;) = S (doble k&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = false&lt;br /&gt;
                                  HI : exists k : nat, n&amp;#039; = S (doble k)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if esPar (S n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite esPar_S.         (* exists k : nat,&lt;br /&gt;
                                   S n&amp;#039; = (if negacion (esPar n&amp;#039;) &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      rewrite H.               (* exists k : nat, &lt;br /&gt;
                                   S n&amp;#039; = (if negacion false &lt;br /&gt;
                                           then doble k &lt;br /&gt;
                                           else S (doble k)) *)&lt;br /&gt;
      simpl.                   (* exists k : nat, S n&amp;#039; = doble k *)&lt;br /&gt;
      destruct HI as [k&amp;#039; Hk&amp;#039;]. (* n&amp;#039; : nat&lt;br /&gt;
                                  H : esPar n&amp;#039; = false&lt;br /&gt;
                                  k&amp;#039; : nat&lt;br /&gt;
                                  Hk&amp;#039; : n&amp;#039; = S (doble k&amp;#039;)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  exists k : nat, S n&amp;#039; = doble k *)&lt;br /&gt;
      exists (1 + k&amp;#039;).              (* S n&amp;#039; = doble (1 + k&amp;#039;) *)&lt;br /&gt;
      rewrite Hk&amp;#039;.             (* S (S (doble k&amp;#039;)) = doble (1 + k&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.2. Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
        esPar n = true &amp;lt;-&amp;gt; exists k, n = doble k.&lt;br /&gt;
&lt;br /&gt;
   Es decir, que la computación booleana (esPar n) refleja la&lt;br /&gt;
   proposición (exists k, n = doble k).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_bool_prop:&lt;br /&gt;
  forall n : nat,&lt;br /&gt;
    esPar n = true &amp;lt;-&amp;gt; exists k, n = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true &amp;lt;-&amp;gt; (exists k : nat, n = doble k) *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                       (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true -&amp;gt; exists k : nat, n = doble k *)&lt;br /&gt;
    intros H.             (* n : nat                           &lt;br /&gt;
                             H : esPar n = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             exists k : nat, n = doble k *)&lt;br /&gt;
    destruct&lt;br /&gt;
      (esPar_doble_aux n) &lt;br /&gt;
      as [k Hk].          (* n : nat&lt;br /&gt;
                             H : esPar n = true&lt;br /&gt;
                             k : nat&lt;br /&gt;
                             Hk : n = (if esPar n then doble k else S (doble k))&lt;br /&gt;
                             ============================&lt;br /&gt;
                             exists k0 : nat, n = doble k0 *)&lt;br /&gt;
    rewrite Hk.           (* exists k0 : nat, &lt;br /&gt;
                              (if esPar n &lt;br /&gt;
                               then doble k &lt;br /&gt;
                               else S (doble k)) &lt;br /&gt;
                              = doble k0 *)&lt;br /&gt;
    rewrite H.            (* exists k0 : nat, doble k = doble k0 *)&lt;br /&gt;
    exists k.                  (* doble k = doble k *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                       (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             (exists k : nat, n = doble k) -&amp;gt; esPar n = true *)&lt;br /&gt;
    intros [k Hk].        (* n, k : nat&lt;br /&gt;
                             Hk : n = doble k&lt;br /&gt;
                             ============================&lt;br /&gt;
                             esPar n = true *)&lt;br /&gt;
    rewrite Hk.           (* esPar (doble k) = true *)&lt;br /&gt;
    apply esPar_doble.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.3. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true &amp;lt;-&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_bool_prop:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true &amp;lt;-&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true &amp;lt;-&amp;gt; n = m *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                           (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true -&amp;gt; n = m *)&lt;br /&gt;
    apply iguales_nat_true.&lt;br /&gt;
  -                           (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = m -&amp;gt; iguales_nat n m = true *)&lt;br /&gt;
    intros H.                 (* n, m : nat&lt;br /&gt;
                                 H : n = m&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 iguales_nat n m = true *)&lt;br /&gt;
    rewrite H.                (* iguales_nat m m = true *)&lt;br /&gt;
    rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.4. Definir la función es_primo_par tal que &lt;br /&gt;
   (es_primo_par n) es verifica si n es un primo par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fail Definition es_primo_par n :=&lt;br /&gt;
  if n = 2&lt;br /&gt;
  then true&lt;br /&gt;
  else false.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Definition es_primo_par n :=&lt;br /&gt;
  if iguales_nat n 2&lt;br /&gt;
  then true&lt;br /&gt;
  else false.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.1. Demostrar que&lt;br /&gt;
      exists k : nat, 1000 = doble k.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000: exists k : nat, 1000 = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  exists 500.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.2. Demostrar que&lt;br /&gt;
      esPar 1000 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000&amp;#039; : esPar 1000 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2.5.3. Demostrar que&lt;br /&gt;
      exists k : nat, 1000 = doble k.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esPar_1000&amp;#039;&amp;#039;: exists k : nat, 1000 = doble k.&lt;br /&gt;
Proof.&lt;br /&gt;
  apply esPar_bool_prop. (* esPar 1000 = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas. &lt;br /&gt;
   1. En la proposicional se necesita proporcionar un testipo.&lt;br /&gt;
   2. En la booleano se calcula sin testigo.&lt;br /&gt;
   3, Se puede demostrar la proposional usando la equivalencia con la&lt;br /&gt;
      booleana sin necesidad de testigo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.2.1. Demostrar que&lt;br /&gt;
      forall x y : bool,&lt;br /&gt;
        x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conj_verdad_syss:&lt;br /&gt;
  forall x y : bool,&lt;br /&gt;
    x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.             (* x, y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             x &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; x = true /\ y = true *)&lt;br /&gt;
  destruct x.             &lt;br /&gt;
  -                       (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; true = true /\ y = true *)&lt;br /&gt;
    destruct y.           &lt;br /&gt;
    +                     (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; true = true &amp;lt;-&amp;gt; true = true /\ true=true *)&lt;br /&gt;
      simpl.              (* true = true &amp;lt;-&amp;gt; true = true /\ true = true *)&lt;br /&gt;
      split.              &lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true -&amp;gt; true = true /\ true = true *)&lt;br /&gt;
        apply conj_intro. (* true = true *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ true = true -&amp;gt; true = true *)&lt;br /&gt;
        apply conj_e1.&lt;br /&gt;
    +                     (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true &amp;amp;&amp;amp; false = true &amp;lt;-&amp;gt; true=true /\ false=true *)&lt;br /&gt;
      simpl.              (* false = true &amp;lt;-&amp;gt; true = true /\ false = true *)&lt;br /&gt;
      split.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true -&amp;gt; true = true /\ false = true *)&lt;br /&gt;
        intros H.         (* H : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ false = true *)&lt;br /&gt;
        inversion H.&lt;br /&gt;
      *                   (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             true = true /\ false = true -&amp;gt; false = true *)&lt;br /&gt;
        intros [H1 H2].   (* H1 : true = true&lt;br /&gt;
                             H2 : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                       (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false &amp;amp;&amp;amp; y = true &amp;lt;-&amp;gt; false = true /\ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                     (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false &amp;amp;&amp;amp; y = true -&amp;gt; false = true /\ y = true *)&lt;br /&gt;
      simpl.              (* false = true -&amp;gt; false = true /\ y = true *)&lt;br /&gt;
      intros H.           (* y : bool&lt;br /&gt;
                             H : false = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true /\ y = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* y : bool&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true /\ y = true -&amp;gt; false &amp;amp;&amp;amp; y = true *)&lt;br /&gt;
      simpl.              (* false = true /\ y = true -&amp;gt; false = true *)&lt;br /&gt;
      intros [H1 H2].     (* y : bool&lt;br /&gt;
                             H1 : false = true&lt;br /&gt;
                             H2 : y = true&lt;br /&gt;
                             ============================&lt;br /&gt;
                             false = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.2.2. Demostrar que&lt;br /&gt;
      forall x y : bool,&lt;br /&gt;
        x || y = true &amp;lt;-&amp;gt; x = true \/ y = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma dist_verdad_syss:&lt;br /&gt;
  forall x y : bool,&lt;br /&gt;
    x || y = true &amp;lt;-&amp;gt; x = true \/ y = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.           (* x, y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           x || y = true &amp;lt;-&amp;gt; x = true \/ y = true *)&lt;br /&gt;
  destruct x.&lt;br /&gt;
  -                     (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true || y = true &amp;lt;-&amp;gt; true = true \/ y = true *)&lt;br /&gt;
    simpl.              (* true = true &amp;lt;-&amp;gt; true = true \/ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true -&amp;gt; true = true \/ y = true *)&lt;br /&gt;
      apply disy_intro. &lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true \/ y = true -&amp;gt; true = true *)&lt;br /&gt;
      intros.           (* y : bool&lt;br /&gt;
                           H : true = true \/ y = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                     (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false || y = true &amp;lt;-&amp;gt; false = true \/ y = true *)&lt;br /&gt;
    simpl.              (* y = true &amp;lt;-&amp;gt; false = true \/ y = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true -&amp;gt; false = true \/ y = true *)&lt;br /&gt;
      destruct y.&lt;br /&gt;
      *                 (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           true = true -&amp;gt; false = true \/ true = true *)&lt;br /&gt;
        intros.         (* H : true = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true \/ true = true *)&lt;br /&gt;
        right.          (* true = true *)&lt;br /&gt;
        reflexivity.&lt;br /&gt;
      *                 (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; false = true \/ false = true *)&lt;br /&gt;
        apply disy_intro.&lt;br /&gt;
    +                   (* y : bool&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true \/ y = true -&amp;gt; y = true *)&lt;br /&gt;
      intros [H1 | H2].&lt;br /&gt;
      *                 (* y : bool&lt;br /&gt;
                           H1 : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true *)&lt;br /&gt;
        inversion H1.&lt;br /&gt;
      *                 (* y : bool&lt;br /&gt;
                           H2 : y = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           y = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
        &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.3. Demostrar que&lt;br /&gt;
      forall x y : nat,&lt;br /&gt;
        iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_falso_syss:&lt;br /&gt;
  forall x y : nat,&lt;br /&gt;
    iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x y.                           (* x, y : nat&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           iguales_nat x y = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
  destruct (iguales_nat x y) eqn:H.&lt;br /&gt;
  -                                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = true&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    rewrite iguales_nat_bool_prop in H. (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    rewrite H.                          (* true = false &amp;lt;-&amp;gt; y &amp;lt;&amp;gt; y *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false -&amp;gt; y &amp;lt;&amp;gt; y *)&lt;br /&gt;
      intros H1.                        (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : true = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           y &amp;lt;&amp;gt; y *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           y &amp;lt;&amp;gt; y -&amp;gt; true = false *)&lt;br /&gt;
      intros H1.                        (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : y &amp;lt;&amp;gt; y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           true = false *)&lt;br /&gt;
      exfalso.                          (* False *)&lt;br /&gt;
      unfold not in H1.                 (* x, y : nat&lt;br /&gt;
                                           H : x = y&lt;br /&gt;
                                           H1 : y = y -&amp;gt; False&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      apply H1.                         (* y = y *)&lt;br /&gt;
      apply eq_refl.&lt;br /&gt;
  -                                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false &amp;lt;-&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false -&amp;gt; x &amp;lt;&amp;gt; y *)&lt;br /&gt;
      unfold not.                       (* false = false -&amp;gt; x = y -&amp;gt; False *)&lt;br /&gt;
      intros H1 H2.                     (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      rewrite H2 in H.                  (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat y y = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      rewrite iguales_nat_refl in H.    (* x, y : nat&lt;br /&gt;
                                           H : true = false&lt;br /&gt;
                                           H1 : false = false&lt;br /&gt;
                                           H2 : x = y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           False *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                                   (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           x &amp;lt;&amp;gt; y -&amp;gt; false = false *)&lt;br /&gt;
      intros.                           (* x, y : nat&lt;br /&gt;
                                           H : iguales_nat x y = false&lt;br /&gt;
                                           H0 : x &amp;lt;&amp;gt; y&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.4.1. Definir la función &lt;br /&gt;
      iguales_lista {A : Type} (i : A -&amp;gt; A -&amp;gt; bool) (xs ys : list A)&lt;br /&gt;
   tal que (iguales_lists xs ys) se verifica si los correspondientes&lt;br /&gt;
   elementos de las listas xs e ys son iguales respecto de la relación&lt;br /&gt;
   de igualdad i.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_lista {A : Type} (i : A -&amp;gt; A -&amp;gt; bool) (xs ys : list A) : bool :=&lt;br /&gt;
  match xs, ys with&lt;br /&gt;
  | nil, nil            =&amp;gt; true&lt;br /&gt;
  | x&amp;#039; ::xs&amp;#039;, y&amp;#039; :: ys&amp;#039; =&amp;gt; i x&amp;#039; y&amp;#039; &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039;&lt;br /&gt;
  | _, _                =&amp;gt; false                          &lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.4.2. Demostrar que&lt;br /&gt;
      forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
        (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
        forall xs ys, iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs = ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_CN:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, iguales_lista i xs ys = true -&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs.                  (* A : Type&lt;br /&gt;
                                       i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                       H : forall x y : A, &lt;br /&gt;
                                            i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                       xs : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i xs ys = true -&amp;gt; xs=ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HIxs&amp;#039;].&lt;br /&gt;
  -                                 (* A : Type&lt;br /&gt;
                                       i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                       H : forall x y : A, &lt;br /&gt;
                                            i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i [ ] ys = true -&amp;gt; &lt;br /&gt;
                                        [ ] = ys *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                               (* iguales_lista i [ ] [ ] = true -&amp;gt; &lt;br /&gt;
                                       [ ] = [ ] *)&lt;br /&gt;
      intros.                       (*   H0 : iguales_lista i [ ] [ ] = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       [ ] = [ ] *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                               (* y : A&lt;br /&gt;
                                       ys&amp;#039; : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       iguales_lista i [ ] (y :: ys&amp;#039;) = true &lt;br /&gt;
                                       -&amp;gt; [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      simpl.                        (* false = true -&amp;gt; [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      intros H1.                    (* H1 : false = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       [ ] = y :: ys&amp;#039; *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                                 (* x : A&lt;br /&gt;
                                       xs&amp;#039; : list A&lt;br /&gt;
                                       HIxs&amp;#039; : forall ys : list A, &lt;br /&gt;
                                                iguales_lista i xs&amp;#039; ys = true &lt;br /&gt;
                                                -&amp;gt; xs&amp;#039; = ys&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       forall ys : list A, &lt;br /&gt;
                                        iguales_lista i (x :: xs&amp;#039;) ys = true &lt;br /&gt;
                                        -&amp;gt; x :: xs&amp;#039; = ys *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                               (* iguales_lista i (x :: xs&amp;#039;) [ ] = true &lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      simpl.                        (* false = true -&amp;gt; x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      intros H1.                    (* H1 : false = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                               (* y : A&lt;br /&gt;
                                       ys&amp;#039; : list A&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       iguales_lista i (x::xs&amp;#039;) (y::ys&amp;#039;) = true&lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      simpl.                        (* i x y &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       -&amp;gt; x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      intros H1.                    (* H1 : i x y &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; ys&amp;#039; = &lt;br /&gt;
                                            true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      apply conj_verdad_syss in H1. (* H1 : i x y = true /\ &lt;br /&gt;
                                            iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      destruct H1 as [H2 H3].       (* H2 : i x y = true&lt;br /&gt;
                                       H3 : iguales_lista i xs&amp;#039; ys&amp;#039; = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       x :: xs&amp;#039; = y :: ys&amp;#039; *)&lt;br /&gt;
      f_equal.&lt;br /&gt;
      *                             (* x = y *)&lt;br /&gt;
        apply H.                    (* i x y = true *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
      *                             (* xs&amp;#039; = ys&amp;#039; *)&lt;br /&gt;
        apply HIxs&amp;#039;.                (* iguales_lista i xs&amp;#039; ys&amp;#039; = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_CS:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, xs = ys -&amp;gt; iguales_lista i xs ys = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs.                (* A : Type&lt;br /&gt;
                                     i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                     H : forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                     xs : list A&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall ys : &lt;br /&gt;
                                      list A, xs = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i xs ys = true *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HIxs&amp;#039;]. &lt;br /&gt;
  -                               (* forall ys : &lt;br /&gt;
                                      list A, [ ] = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i [ ] ys = true *)&lt;br /&gt;
    intros ys H1.                 (* ys : list A&lt;br /&gt;
                                     H1 : [ ] = ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     iguales_lista i [ ] ys = true *)&lt;br /&gt;
    rewrite &amp;lt;- H1.                 (* iguales_lista i [ ] [ ] = true *)&lt;br /&gt;
    simpl.                        (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                               (* x : A&lt;br /&gt;
                                     xs&amp;#039; : list A&lt;br /&gt;
                                     HIxs&amp;#039; : forall ys : &lt;br /&gt;
                                              list A, xs&amp;#039; = ys -&amp;gt; &lt;br /&gt;
                                              iguales_lista i xs&amp;#039; ys = true&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     forall ys : &lt;br /&gt;
                                      list A, x :: xs&amp;#039; = ys -&amp;gt; &lt;br /&gt;
                                      iguales_lista i (x :: xs&amp;#039;) ys = true *)&lt;br /&gt;
    intros ys H1.                 (* ys : list A&lt;br /&gt;
                                     H1 : x :: xs&amp;#039; = ys&lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     iguales_lista i (x :: xs&amp;#039;) ys = true *)&lt;br /&gt;
    rewrite &amp;lt;-H1.                  (* iguales_lista i (x::xs&amp;#039;) (x::xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                        (* i x x &amp;amp;&amp;amp; iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    apply conj_verdad_syss.       (* i x x = true /\ &lt;br /&gt;
                                     iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                             (* i x x = true *)&lt;br /&gt;
      apply H.                    (* x = x *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                             (* iguales_lista i xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
      apply HIxs&amp;#039;.                (* xs&amp;#039; = xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma iguales_lista_verdad_syss:&lt;br /&gt;
  forall A (i : A -&amp;gt; A -&amp;gt; bool),&lt;br /&gt;
    (forall x y, i x y = true &amp;lt;-&amp;gt; x = y) -&amp;gt;&lt;br /&gt;
    forall xs ys, iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A i H xs ys.              (* A : Type&lt;br /&gt;
                                      i : A -&amp;gt; A -&amp;gt; bool&lt;br /&gt;
                                      H : forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y&lt;br /&gt;
                                      xs, ys : list A&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      iguales_lista i xs ys = true &amp;lt;-&amp;gt; xs=ys *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                                (* iguales_lista i xs ys = true -&amp;gt; xs = ys *)&lt;br /&gt;
    apply iguales_lista_verdad_CN. (* forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y *)&lt;br /&gt;
    apply H.&lt;br /&gt;
  -                                (* xs = ys -&amp;gt; iguales_lista i xs ys = true *)&lt;br /&gt;
    apply iguales_lista_verdad_CS. (* forall x y : A, i x y = true &amp;lt;-&amp;gt; x = y *)&lt;br /&gt;
    apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2.5. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
        todos p xs = true &amp;lt;-&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_CN:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    todos p xs = true -&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.                 (* X : Type&lt;br /&gt;
                                    p : X -&amp;gt; bool&lt;br /&gt;
                                    xs : list X&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    todos p xs = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].&lt;br /&gt;
  -                              (* todos p [ ] = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) [ ] *)&lt;br /&gt;
    simpl.                       (* true = true -&amp;gt; True *)&lt;br /&gt;
    intros.                      (* H : true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    True *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* x&amp;#039; : X&lt;br /&gt;
                                    xs&amp;#039; : list X&lt;br /&gt;
                                    HI : todos p xs&amp;#039; = true -&amp;gt; &lt;br /&gt;
                                         Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    todos p (x&amp;#039; :: xs&amp;#039;) = true -&amp;gt; &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) (x&amp;#039;::xs&amp;#039;) *)&lt;br /&gt;
    simpl.                       (* p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true -&amp;gt;&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    intros H.                    (* H : p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    apply conj_verdad_syss in H. (* H :p x&amp;#039; = true /\ todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    destruct H as [H1 H2].       (* H1 : p x&amp;#039; = true&lt;br /&gt;
                                    H2 : todos p xs&amp;#039; = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    p x&amp;#039; = true /\ &lt;br /&gt;
                                    Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                            (* p x&amp;#039; = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
      apply HI.                  (* todos p xs&amp;#039; = true *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_CS:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    Todos (fun x =&amp;gt; p x = true) xs -&amp;gt; todos p xs = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.                (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) xs -&amp;gt; &lt;br /&gt;
                                   todos p xs = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* Todos (fun x : X =&amp;gt; p x = true) [ ] -&amp;gt; &lt;br /&gt;
                                   todos p [ ] = true *)&lt;br /&gt;
    simpl.                      (* True -&amp;gt; true = true *)&lt;br /&gt;
    intros.                     (* H : True&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI : Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; -&amp;gt; &lt;br /&gt;
                                        todos p xs&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) (x&amp;#039; :: xs&amp;#039;) &lt;br /&gt;
                                   -&amp;gt; todos p (x&amp;#039; :: xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                      (* p x&amp;#039; = true /\ &lt;br /&gt;
                                   Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; -&amp;gt;&lt;br /&gt;
                                   p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true *)&lt;br /&gt;
    intros [H1 H2].             (* H1 : p x&amp;#039; = true&lt;br /&gt;
                                   H2 : Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x&amp;#039; &amp;amp;&amp;amp; todos p xs&amp;#039; = true *)&lt;br /&gt;
    apply conj_verdad_syss.     (* p x&amp;#039; = true /\ todos p xs&amp;#039; = true *)&lt;br /&gt;
    split.&lt;br /&gt;
    +                           (* p x&amp;#039; = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                           (* todos p xs&amp;#039; = true *)&lt;br /&gt;
      apply HI.                 (* Todos (fun x : X =&amp;gt; p x = true) xs&amp;#039; *)&lt;br /&gt;
      apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem todos_verdad_syss:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    todos p xs = true &amp;lt;-&amp;gt; Todos (fun x =&amp;gt; p x = true) xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.           (* X : Type&lt;br /&gt;
                              p : X -&amp;gt; bool&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              ============================&lt;br /&gt;
                              todos p xs = true &amp;lt;-&amp;gt; &lt;br /&gt;
                              Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
  split.&lt;br /&gt;
  -                        (* todos p xs = true -&amp;gt; &lt;br /&gt;
                              Todos (fun x : X =&amp;gt; p x = true) xs *)&lt;br /&gt;
    apply todos_verdad_CN. &lt;br /&gt;
  -                        (* Todos (fun x : X =&amp;gt; p x = true) xs -&amp;gt; &lt;br /&gt;
                              todos p xs = true *)&lt;br /&gt;
    apply todos_verdad_CS.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 5.3. Lógica clásica vs. constructiva  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.1. Definir la proposicion&lt;br /&gt;
      tercio_excluso&lt;br /&gt;
   que afirma que  (forall P : Prop, P \/ ~ P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Definition tercio_excluso : Prop := forall P : Prop,&lt;br /&gt;
  P \/ ~ P.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. La proposión tercio_excluso no es demostrable en Coq.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.2. Demostrar que&lt;br /&gt;
      forall (P : Prop) (b : bool),&lt;br /&gt;
        (P &amp;lt;-&amp;gt; b = true) -&amp;gt; P \/ ~ P.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_exluso_restringido :&lt;br /&gt;
  forall (P : Prop) (b : bool),&lt;br /&gt;
    (P &amp;lt;-&amp;gt; b = true) -&amp;gt; P \/ ~ P.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P [] H.  &lt;br /&gt;
  -               (* P : Prop&lt;br /&gt;
                     H : P &amp;lt;-&amp;gt; true = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     P \/ ~ P *)&lt;br /&gt;
    left.         (* P *)&lt;br /&gt;
    rewrite H.    (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* P : Prop&lt;br /&gt;
                     H : P &amp;lt;-&amp;gt; false = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     P \/ ~ P *)&lt;br /&gt;
    right.        (* ~ P *)&lt;br /&gt;
    rewrite H.    (* false &amp;lt;&amp;gt; true *)&lt;br /&gt;
    intros H1.    (* H1 : false = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     False *)&lt;br /&gt;
    inversion H1. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        n = m \/ n &amp;lt;&amp;gt; m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_exluso_restringido_eq:&lt;br /&gt;
  forall (n m : nat),&lt;br /&gt;
    n = m \/ n &amp;lt;&amp;gt; m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                      (* n, m : nat&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      n = m \/ n &amp;lt;&amp;gt; m *)&lt;br /&gt;
  apply (tercio_exluso_restringido &lt;br /&gt;
           (n = m)&lt;br /&gt;
           (iguales_nat n m)).     (* n = m &amp;lt;-&amp;gt; iguales_nat n m = true *)&lt;br /&gt;
  symmetry.                        (* iguales_nat n m = true &amp;lt;-&amp;gt; n = m *)&lt;br /&gt;
  apply iguales_nat_bool_prop.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Notas.&lt;br /&gt;
   1. En Coq no se puede demostrar el principio del tercio exluso.&lt;br /&gt;
   2. Las demostraciones de las fórmulas existenciales tienen que&lt;br /&gt;
      proporcionar un testigo.&lt;br /&gt;
   2. la lógica de Coq es constructiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.1. Demostrar que&lt;br /&gt;
      forall (P : Prop),&lt;br /&gt;
        ~ ~ (P \/ ~ P).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_irrefutable:&lt;br /&gt;
  forall (P : Prop),&lt;br /&gt;
    ~ ~ (P \/ ~ P).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros P.   (* P : Prop&lt;br /&gt;
                 ============================&lt;br /&gt;
                 ~ ~ (P \/ ~ P) *)&lt;br /&gt;
  unfold not. (* (P \/ (P -&amp;gt; False) -&amp;gt; False) -&amp;gt; False *)&lt;br /&gt;
  intros H.   (* H : P \/ (P -&amp;gt; False) -&amp;gt; False&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply H.    (* P \/ (P -&amp;gt; False) *)&lt;br /&gt;
  right.      (* P -&amp;gt; False *)&lt;br /&gt;
  intro H1.   (* H1 : P&lt;br /&gt;
                 ============================&lt;br /&gt;
                 False *)&lt;br /&gt;
  apply H.    (* P \/ (P -&amp;gt; False) *)&lt;br /&gt;
  left.       (* P *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El teorema anterior garantiza que añadir el tercio excluso como&lt;br /&gt;
   axioma no provoca contradicción.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.2. Demostrar que&lt;br /&gt;
      tercio_excluso -&amp;gt;&lt;br /&gt;
      forall (X : Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
        ~ (exists x, ~ P x) -&amp;gt; (forall x, P x).&lt;br /&gt;
&lt;br /&gt;
   Nota. La condición del tercio_excluso es necesaria.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem no_existe_no:&lt;br /&gt;
  tercio_excluso -&amp;gt;&lt;br /&gt;
  forall (X : Type) (P : X -&amp;gt; Prop),&lt;br /&gt;
    ~ (exists x, ~ P x) -&amp;gt; (forall x, P x).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 X P H2 x.          (* H1 : tercio_excluso&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  P : X -&amp;gt; Prop&lt;br /&gt;
                                  H2 : ~ (exists x : X, ~ P x)&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
  unfold tercio_excluso in H1. (* H1 : forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  assert (P x \/ ~ P x).&lt;br /&gt;
  -                            (* P x \/ ~ P x *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                            (* H : P x \/ ~ P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
    destruct H as [H3 | H4].&lt;br /&gt;
    +                          (* x : X&lt;br /&gt;
                                  H3 : P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                          (* x : X&lt;br /&gt;
                                  H4 : ~ P x&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  P x *)&lt;br /&gt;
      exfalso.                 (* False *)&lt;br /&gt;
      apply H2.                (* exists x0 : X, ~ P x0 *)&lt;br /&gt;
      exists x.                     (* ~ P x *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.1. En este ejercico se van a demostrar 4 formas&lt;br /&gt;
   equivalentes del principio del tercio excluso. &lt;br /&gt;
&lt;br /&gt;
   Sea peirce la proposición definida por&lt;br /&gt;
      Definition peirce: Prop := forall P Q : Prop,&lt;br /&gt;
        ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; peirce &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition peirce: Prop := forall P Q : Prop,&lt;br /&gt;
  ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_peirce_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; peirce.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.     (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                (forall P : Prop, P \/ ~ P) -&amp;gt; peirce *)&lt;br /&gt;
  unfold peirce.             (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P *)&lt;br /&gt;
  intros H1 P Q H2.          (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                P, Q : Prop&lt;br /&gt;
                                H2 : (P -&amp;gt; Q) -&amp;gt; P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                          (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* H : P \/ ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                        (* H3 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                        (* H4 : ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P *)&lt;br /&gt;
      apply H2.              (* P -&amp;gt; Q *)&lt;br /&gt;
      intros H5.             (* H5 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
      exfalso.               (* False *)&lt;br /&gt;
      apply H4.              (* P *)&lt;br /&gt;
      apply H5.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_peirce_L2:&lt;br /&gt;
  peirce -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold peirce.         (* &lt;br /&gt;
                            ============================&lt;br /&gt;
                            (forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                            tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso. (* (forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                            forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H P.            (* H : forall P Q : Prop, ((P -&amp;gt; Q) -&amp;gt; P) -&amp;gt; P&lt;br /&gt;
                            P : Prop&lt;br /&gt;
                            ============================&lt;br /&gt;
                            P \/ ~ P *)&lt;br /&gt;
  apply H with (Q := False). (* (P \/ ~ P -&amp;gt; False) -&amp;gt; P \/ ~ P *)&lt;br /&gt;
  intros H1.             (* H1 : P \/ ~ P -&amp;gt; False&lt;br /&gt;
                            ============================&lt;br /&gt;
                            P \/ ~ P *)&lt;br /&gt;
  right.                 (* ~ P *)&lt;br /&gt;
  unfold not.            (* P -&amp;gt; False *)&lt;br /&gt;
  intros H2.             (* H2 : P&lt;br /&gt;
                            ============================&lt;br /&gt;
                            False *)&lt;br /&gt;
  apply H1.              (* P \/ ~ P *)&lt;br /&gt;
  left.                  (* P *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_peirce:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; peirce.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -                                 (* &lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       tercio_excluso -&amp;gt; peirce *)&lt;br /&gt;
    apply tercio_excluso_peirce_L1. &lt;br /&gt;
  -                                 (* &lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       peirce -&amp;gt; tercio_excluso *)&lt;br /&gt;
    apply tercio_excluso_peirce_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.2. Sea eliminacion_doble_negacion la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition eliminacion_doble_negacion: Prop := forall P : Prop,&lt;br /&gt;
        ~~P -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; eliminacion_doble_negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition eliminacion_doble_negacion: Prop := forall P : Prop,&lt;br /&gt;
  ~~P -&amp;gt; P.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; eliminacion_doble_negacion.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.             (* &lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                        eliminacion_doble_negacion *)&lt;br /&gt;
  unfold eliminacion_doble_negacion. (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                        forall P : Prop, ~ ~ P -&amp;gt; P *)&lt;br /&gt;
  intros H1 P H2.                    (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                        P : Prop&lt;br /&gt;
                                        H2 : ~ ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                                  (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                  (* H : P \/ ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
    destruct H as [H3 | H4].&lt;br /&gt;
    +                                (* H2 : ~ ~ P&lt;br /&gt;
                                        H3 : P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                                (* H4 : ~ P&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P *)&lt;br /&gt;
      exfalso.                       (* False *)&lt;br /&gt;
      apply H2.                      (* ~ P *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion_L2:&lt;br /&gt;
  eliminacion_doble_negacion -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold eliminacion_doble_negacion. (* &lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        (forall P : Prop, ~ ~ P -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                                        tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.             (* (forall P : Prop, ~ ~ P -&amp;gt; P) -&amp;gt; &lt;br /&gt;
                                        forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H P.                        (* H : forall P : Prop, ~ ~ P -&amp;gt; P&lt;br /&gt;
                                        P : Prop&lt;br /&gt;
                                        ============================&lt;br /&gt;
                                        P \/ ~ P *)&lt;br /&gt;
  apply H.                           (* ~ ~ (P \/ ~ P) *)&lt;br /&gt;
  apply tercio_excluso_irrefutable.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_eliminacion_doble_negacion:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; eliminacion_doble_negacion.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_eliminacion_doble_negacion_L1.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_eliminacion_doble_negacion_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.3. Sea morgan_no_no la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition de_morgan_no_no: Prop :=&lt;br /&gt;
        forall P Q : Prop, ~(~P /\ ~Q) -&amp;gt; P \/ Q.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; morgan_no_no&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition de_morgan_no_no: Prop :=&lt;br /&gt;
  forall P Q : Prop, ~(~P /\ ~Q) -&amp;gt; P \/ Q.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; de_morgan_no_no.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.     (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                de_morgan_no_no *)&lt;br /&gt;
  unfold de_morgan_no_no.    (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q *)&lt;br /&gt;
  intros H1 P Q H2.          (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                P, Q : Prop&lt;br /&gt;
                                H2 : ~ (~ P /\ ~ Q)&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                          (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                          (* H : P \/ ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                        (* H2 : ~ (~ P /\ ~ Q)&lt;br /&gt;
                                H3 : P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
      left.                  (* P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                        (* H4 : ~ P&lt;br /&gt;
                                ============================&lt;br /&gt;
                                P \/ Q *)&lt;br /&gt;
      right.                 (* Q *)&lt;br /&gt;
      assert (Q \/ ~ Q).&lt;br /&gt;
      *                      (* Q \/ ~ Q *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                      (* H : Q \/ ~ Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
        destruct H as [H5 | H6].&lt;br /&gt;
        --                   (* H5 : Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
          apply H5.&lt;br /&gt;
        --                   (* H6 : ~ Q&lt;br /&gt;
                                ============================&lt;br /&gt;
                                Q *)&lt;br /&gt;
          exfalso.           (* False *)&lt;br /&gt;
          apply H2.          (* ~ P /\ ~ Q *)&lt;br /&gt;
          split.&lt;br /&gt;
          ++                 (* ~ P *)&lt;br /&gt;
            apply H4.&lt;br /&gt;
          ++                 (* ~ Q *)&lt;br /&gt;
            apply H6.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no_L2:&lt;br /&gt;
  de_morgan_no_no -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold de_morgan_no_no. (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             (forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q) -&amp;gt; &lt;br /&gt;
                             tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.  (* (forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q) -&amp;gt; &lt;br /&gt;
                             forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H1 P.            (* H1 : forall P Q : Prop, ~ (~ P /\ ~ Q) -&amp;gt; P \/ Q&lt;br /&gt;
                             P : Prop&lt;br /&gt;
                             ============================&lt;br /&gt;
                             P \/ ~ P *)&lt;br /&gt;
  apply H1.               (* ~ (~ P /\ ~ ~ P) *)&lt;br /&gt;
  intros H2.              (* H2 : ~ P /\ ~ ~ P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             False *)&lt;br /&gt;
  destruct H2 as (H3,H4). (* H3 : ~ P&lt;br /&gt;
                             H4 : ~ ~ P&lt;br /&gt;
                             ============================&lt;br /&gt;
                             False *)&lt;br /&gt;
  apply H4.               (* ~ P *)&lt;br /&gt;
  apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_de_morgan_no_no:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; de_morgan_no_no.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_de_morgan_no_no_L1.&lt;br /&gt;
  -&lt;br /&gt;
    apply tercio_excluso_equiv_de_morgan_no_no_L2.&lt;br /&gt;
Qed.&lt;br /&gt;
  &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3.4. Sea condicional_a_disyuncion la proposición&lt;br /&gt;
   definida por &lt;br /&gt;
      Definition condicional_a_disyuncion: Prop :=&lt;br /&gt;
        forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; (~P \/ Q).&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      tercio_excluso &amp;lt;-&amp;gt; morgan_no_no&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition condicional_a_disyuncion: Prop :=&lt;br /&gt;
  forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; (~P \/ Q).&lt;br /&gt;
&lt;br /&gt;
Lemma tercio_excluso_equiv_condicional_a_disyuncion_L1:&lt;br /&gt;
  tercio_excluso -&amp;gt; condicional_a_disyuncion.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold tercio_excluso.           (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                      condicional_a_disyuncion *)&lt;br /&gt;
  unfold condicional_a_disyuncion. (* (forall P : Prop, P \/ ~ P) -&amp;gt; &lt;br /&gt;
                                      forall P Q : Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q *)&lt;br /&gt;
  intros H1 P Q H2.                (* H1 : forall P : Prop, P \/ ~ P&lt;br /&gt;
                                      P, Q : Prop&lt;br /&gt;
                                      H2 : P -&amp;gt; Q&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
  assert (P \/ ~P).&lt;br /&gt;
  -                                (* P \/ ~ P *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                (* H : P \/ ~ P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
    destruct H as [H3 | H4]. &lt;br /&gt;
    +                              (* H3 : P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
      right.                       (* Q *)&lt;br /&gt;
      apply H2.                    (* P *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
    +                              (* H4 : ~ P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      ~ P \/ Q *)&lt;br /&gt;
      left.                        (* ~ P *)&lt;br /&gt;
      apply H4.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Lemma tercio_excluso_equiv_condicional_a_disyuncion_L2:&lt;br /&gt;
  condicional_a_disyuncion -&amp;gt; tercio_excluso.&lt;br /&gt;
Proof.&lt;br /&gt;
  unfold condicional_a_disyuncion. (* &lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      (forall P Q:Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q) &lt;br /&gt;
                                      -&amp;gt; tercio_excluso *)&lt;br /&gt;
  unfold tercio_excluso.           (* (forall P Q:Prop, (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q) &lt;br /&gt;
                                      -&amp;gt; forall P : Prop, P \/ ~ P *)&lt;br /&gt;
  intros H1 P.                     (* H1 : forall P Q : Prop, &lt;br /&gt;
                                            (P -&amp;gt; Q) -&amp;gt; ~ P \/ Q&lt;br /&gt;
                                      P : Prop&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      P \/ ~ P *)&lt;br /&gt;
  apply disy_conmutativa.          (* ~ P \/ P *)&lt;br /&gt;
  apply H1.                        (* P -&amp;gt; P *)&lt;br /&gt;
  intros.                          (* H : P&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      P *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem tercio_excluso_equiv_condicional_a_disyuncion:&lt;br /&gt;
  tercio_excluso &amp;lt;-&amp;gt; condicional_a_disyuncion.&lt;br /&gt;
Proof.&lt;br /&gt;
  split.&lt;br /&gt;
  - apply tercio_excluso_equiv_condicional_a_disyuncion_L1.&lt;br /&gt;
  - apply tercio_excluso_equiv_condicional_a_disyuncion_L2.&lt;br /&gt;
Qed.    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Logic.html Logic in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=70</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=70"/>
		<updated>2018-08-20T10:41:35Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;br /&gt;
* [[Tema 4: Polimorfismo y funciones de orden superior en Coq]].&lt;br /&gt;
* [[Tema 5: Tácticas básicas de Coq]].&lt;br /&gt;
* [[Tema 6: Lógica en Coq]].&lt;br /&gt;
&lt;br /&gt;
=== Código ===&lt;br /&gt;
&lt;br /&gt;
El código correspondiente se encuentra en [https://github.com/jaalonso/DAOconCoq GitHub].&lt;br /&gt;
&lt;br /&gt;
=== Libro ===&lt;br /&gt;
&lt;br /&gt;
Todos los temas están recopilados en el libro [https://github.com/jaalonso/DAOconCoq/raw/master/texto/DAOconCoq.pdf Demostración asistida por ordenador con Coq].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=69</id>
		<title>Tema 5: Tácticas básicas de Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=69"/>
		<updated>2018-08-12T07:57:08Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se amplían las tácticas básicas estudiadas en los temas anteriores. Al final de la teoría se incluye un resumen de todas las tácticas usadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T5_Tacticas.v|T5_Tacticas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T5: Tácticas básicas de Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T4_PolimorfismoyOS.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   5. Control de la hipótesis de inducción  &lt;br /&gt;
   6. Expansión de definiciones &lt;br /&gt;
   7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   8. Ejercicios &lt;br /&gt;
   9. Resumen de tácticas básicas &lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que &lt;br /&gt;
          n = m  -&amp;gt;&lt;br /&gt;
          [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
          [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración sin apply *)&lt;br /&gt;
Theorem artificial_1a : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  rewrite H2.           (* [n; p] = [n; p] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* Demostración con apply *)&lt;br /&gt;
Theorem artificial_1b : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que &lt;br /&gt;
      n = m  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
      [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2 : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : forall q r : nat, q = r -&amp;gt; [q; o] = [r; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  apply H2.             (* n = m *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039; en hipótesis condicionales y&lt;br /&gt;
   razonamiento hacia atrás&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Demostrar que &lt;br /&gt;
      (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
      [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2a : forall (n m : nat),&lt;br /&gt;
    (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H1 H2. (* n, m : nat&lt;br /&gt;
                       H1 : (n, n) = (m, m)&lt;br /&gt;
                       H2 : forall q r : nat, (q, q) = (r, r) -&amp;gt; [q] = [r]&lt;br /&gt;
                       ============================&lt;br /&gt;
                       [n] = [m] *)&lt;br /&gt;
  apply H2.         (* (n, n) = (m, m) *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar, sin usar simpl, que&lt;br /&gt;
      (forall n, evenb n = true -&amp;gt; oddb (S n) = true) -&amp;gt;&lt;br /&gt;
      evenb 3 = true -&amp;gt;&lt;br /&gt;
      oddb 4 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial_ex :&lt;br /&gt;
  (forall n, esPar n = true -&amp;gt; esImpar (S n) = true) -&amp;gt;&lt;br /&gt;
  esPar 3 = true -&amp;gt;&lt;br /&gt;
  esImpar 4 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 H2. (* H1 : forall n : nat, esPar n = true -&amp;gt; esImpar (S n) = true&lt;br /&gt;
                   H2 : esPar 3 = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   esImpar 4 = true *)&lt;br /&gt;
  apply H1.     (* esPar 3 = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Demostrar que &lt;br /&gt;
      true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
      iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3a: forall (n : nat),&lt;br /&gt;
    true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
    iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H. (* n : nat&lt;br /&gt;
                 H : true = iguales_nat n 5&lt;br /&gt;
                 ============================&lt;br /&gt;
                 iguales_nat (S (S n)) 7 = true *)&lt;br /&gt;
  symmetry.   (* true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  simpl.      (* true = iguales_nat n 5 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Necesidad de usar symmetry antes de apply.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar&lt;br /&gt;
      forall (xs ys : list nat), &lt;br /&gt;
       xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa2: forall (xs ys : list nat),&lt;br /&gt;
    xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.           (* xs, ys : list nat&lt;br /&gt;
                               H : xs = inversa ys&lt;br /&gt;
                               ============================&lt;br /&gt;
                               ys = inversa xs *)&lt;br /&gt;
  rewrite H.                (* ys = inversa (inversa ys) *)&lt;br /&gt;
  symmetry.                 (* inversa (inversa ys) = ys *)&lt;br /&gt;
  apply inversa_involutiva. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall (a b c d e f : nat),&lt;br /&gt;
       [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
       [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
       [a;b] = [e;f].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejemplo_con_transitiva: forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2. (* a, b, c, d, e, f : nat&lt;br /&gt;
                               H1 : [a; b] = [c; d]&lt;br /&gt;
                               H2 : [c; d] = [e; f]&lt;br /&gt;
                               ============================&lt;br /&gt;
                               [a; b] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H1.             (* [c; d] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H2.             (* [e; f] = [e; f] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem igualdad_transitiva: forall (X:Type) (n m o : X),&lt;br /&gt;
    n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X n m o H1 H2. (* X : Type&lt;br /&gt;
                           n, m, o : X&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : m = o&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.         (* m = o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.         (* o = o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El ejercicio 2.2 es una generalización del 2.1, sus&lt;br /&gt;
   demostraciones son isomorfas y se puede usar el 2.2 en la&lt;br /&gt;
   demostración del 2.1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.                  (* a, b, c, d, e, f : nat&lt;br /&gt;
                                                H1 : [a; b] = [c; d]&lt;br /&gt;
                                                H2 : [c; d] = [e; f]&lt;br /&gt;
                                                ============================&lt;br /&gt;
                                                [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with (m:=[c;d]).&lt;br /&gt;
  -                                          (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                          (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039;&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.             (* a, b, c, d, e, f : nat&lt;br /&gt;
                                           H1 : [a; b] = [c; d]&lt;br /&gt;
                                           H2 : [c; d] = [e; f]&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with [c;d].&lt;br /&gt;
  -                                     (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                     (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply ... whith ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1. Demostrar que&lt;br /&gt;
      forall (n m o p : nat),&lt;br /&gt;
        m = (menosDos o) -&amp;gt;&lt;br /&gt;
        (n + p) = m -&amp;gt;&lt;br /&gt;
        (n + p) = (menosDos o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_igualdad_transitiva: forall (n m o p : nat),&lt;br /&gt;
    m = (menosDos o) -&amp;gt;&lt;br /&gt;
    (n + p) = m -&amp;gt;&lt;br /&gt;
    (n + p) = (menosDos o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2.             (* n, m, o, p : nat&lt;br /&gt;
                                       H1 : m = menosDos o&lt;br /&gt;
                                       H2 : n + p = m&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n + p = menosDos o *)&lt;br /&gt;
  apply igualdad_transitiva with m. &lt;br /&gt;
  -                                 (* n + p = m *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
  -                                 (* m = menosDos o *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       S n = S m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inyectiva: forall (n m : nat),&lt;br /&gt;
  S n = S m -&amp;gt;&lt;br /&gt;
  n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (n m o : nat),&lt;br /&gt;
       [n; m] = [o; o] -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej1: forall (n m o : nat),&lt;br /&gt;
    [n; m] = [o; o] -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H. (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [n] = [m] *)&lt;br /&gt;
  inversion H.    (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     H1 : n = o&lt;br /&gt;
                     H2 : m = o&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [o] = [o] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       [n] = [m] -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej2: forall (n m : nat),&lt;br /&gt;
    [n] = [m] -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.         (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = m *)&lt;br /&gt;
  inversion H as [Hnm]. (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           Hnm : n = m&lt;br /&gt;
                           ============================&lt;br /&gt;
                           m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Nombramiento de las hipótesis generadas por inversión.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
        x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej3 : forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
  x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
  y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
  x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H1 H2. (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x = y *)&lt;br /&gt;
  inversion H1.               (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = y *)&lt;br /&gt;
  inversion H2.               (* xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 H4 : y = x&lt;br /&gt;
                                 H5 : xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = x *)&lt;br /&gt;
  symmetry.                   (* x = z *)&lt;br /&gt;
  apply H0.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.4. Demostrar que&lt;br /&gt;
      forall n:nat,&lt;br /&gt;
       iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_0_n: forall n:nat,&lt;br /&gt;
    iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 n = true -&amp;gt; n = 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
    intros H.           (* H : iguales_nat 0 0 = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 (S n&amp;#039;) = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    intros H.           (* n&amp;#039; : nat&lt;br /&gt;
                           H : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           S n&amp;#039; = 0 *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.5. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       S n = O -&amp;gt; 2 + 2 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej4: forall (n : nat),&lt;br /&gt;
    S n = O -&amp;gt;&lt;br /&gt;
    2 + 2 = 5.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.  (* n : nat&lt;br /&gt;
                  H : S n = 0&lt;br /&gt;
                  ============================&lt;br /&gt;
                  2 + 2 = 5 *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.6. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       false = true -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej5: forall (n m : nat),&lt;br /&gt;
    false = true -&amp;gt; [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : false = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   [n] = [m] *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
        y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        x = z.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej6 :&lt;br /&gt;
  forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
    x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
    y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
    x = z.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H. (* X : Type&lt;br /&gt;
                             x, y, z : X&lt;br /&gt;
                             xs, ys : list X&lt;br /&gt;
                             H : x :: y :: xs = [ ]&lt;br /&gt;
                             ============================&lt;br /&gt;
                             y :: xs = z :: ys -&amp;gt; x = z *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.  &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.7. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
       x = y -&amp;gt; f x = f y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem funcional: forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
    x = y -&amp;gt; f x = f y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f x y H. (* A : Type&lt;br /&gt;
                         B : Type&lt;br /&gt;
                         f : A -&amp;gt; B&lt;br /&gt;
                         x, y : A&lt;br /&gt;
                         H : x = y&lt;br /&gt;
                         ============================&lt;br /&gt;
                         f x = f y *)&lt;br /&gt;
  rewrite H.          (* f y = f y *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n m : nat) (b : bool),&lt;br /&gt;
       iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
       iguales_nat n m = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inj: forall (n m : nat) (b : bool),&lt;br /&gt;
    iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
    iguales_nat n m = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m b H. (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat (S n) (S m) = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  simpl in H.     (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat n m = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de táctica &amp;#039;simpl in ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
       true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
       true = iguales_nat (S (S n)) 7.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3&amp;#039;: forall (n : nat),&lt;br /&gt;
  (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
  true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
  true = iguales_nat (S (S n)) 7.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H1 H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat n 5&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat n 5 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H1 in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat (S (S n)) 7&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de las tácticas &amp;#039;apply H1 in H2&amp;#039; y &amp;#039;symemetry in H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n + n = m + m -&amp;gt;&lt;br /&gt;
        n = m.&lt;br /&gt;
&lt;br /&gt;
   Nota: Usar suma_s_Sm.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_n_inyectiva:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    n + n = m + m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, n + n = m + m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI]. &lt;br /&gt;
  -                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, 0 + 0 = m + m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H1.                 (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* H1 : 0 + 0 = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = S m *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, S n&amp;#039; + S n&amp;#039; = m + m &lt;br /&gt;
                                                    -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H2.                 (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H2.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H2.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : n&amp;#039; + S n&amp;#039; = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (n&amp;#039; + n&amp;#039;) = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H0.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : m + S m = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H0.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : m + m = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      apply HI in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- H1.             (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Control de la hipótesis de inducción  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª intento *)&lt;br /&gt;
Theorem doble_inyectiva_FAILED : forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.             (* n, m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros H.             (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble (S n&amp;#039;) = doble m -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros H.             (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva: forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H.           (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble (S n&amp;#039;) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, S (S (doble n&amp;#039;)) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H.           (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.           (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.        (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la estrategia de generalización.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_true : forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat 0 m = true &lt;br /&gt;
                                              -&amp;gt; 0 = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 (S m&amp;#039;) = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat (S n&amp;#039;) m = true&lt;br /&gt;
                                                   -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) 0 = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                        -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) (S m&amp;#039;) = true &lt;br /&gt;
                                   -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* iguales_nat n&amp;#039; m&amp;#039; = true -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : iguales_nat n&amp;#039; m&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply HIn&amp;#039; in H.          (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      rewrite H.                (* S m&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
    &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2a: forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI].&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                      (* doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros H.                   (* n : nat&lt;br /&gt;
                                   H : doble n = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                           (* H : doble 0 = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.               (* n&amp;#039; : nat&lt;br /&gt;
                                   H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble (S m&amp;#039;) -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
&lt;br /&gt;
    intros H.                   (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.               (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble (S n&amp;#039;) = doble m&amp;#039; -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.          (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2 : forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.               (* n, m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  generalize dependent n.   (* m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI]. &lt;br /&gt;
  -                         (*  &lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                  (* forall n : nat, doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros n H.             (* n : nat&lt;br /&gt;
                               H : doble n = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                       (* H : doble 0 = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                       (* n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.           (* n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                         (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble (S m&amp;#039;) &lt;br /&gt;
                                               -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
    intros n H.             (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n : nat&lt;br /&gt;
                               H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.      (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.             (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.          (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;generalize dependent n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Demostrar que&lt;br /&gt;
      forall x y : id,&lt;br /&gt;
       iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_true: forall x y : id,&lt;br /&gt;
  iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [m] [n].           (* m, n : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id (Id m) (Id n) = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  simpl.                    (* iguales_nat m n = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  intros H.                 (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
  assert (H&amp;#039; : m = n).&lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               m = n *)&lt;br /&gt;
    apply iguales_nat_true. (* iguales_nat m n = true *)&lt;br /&gt;
    apply H. &lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               H&amp;#039; : m = n&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
    rewrite H&amp;#039;.             (* Id n = Id n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar, por inducción sobre l,&lt;br /&gt;
      forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
        longitud xs = n -&amp;gt;&lt;br /&gt;
        nthOpcional xs n = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nthOpcional_None: forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = n -&amp;gt;&lt;br /&gt;
    nthOpcional xs n = None.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n X xs.               (* n : nat&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  generalize dependent n.       (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud [] = n -&amp;gt; nthOpcional [] n = None *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = n -&amp;gt; &lt;br /&gt;
                                   nthOpcional (x :: xs&amp;#039;) n = None *)&lt;br /&gt;
    destruct n as [|n&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = 0 -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) (S n&amp;#039;) = None *)&lt;br /&gt;
      simpl.                    (* S (longitud xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                   nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      apply HI.                 (* longitud xs&amp;#039; = n&amp;#039; *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  H1 : longitud xs&amp;#039; = n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs&amp;#039; = longitud xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 6. Expansión de definiciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.1. Definir la función&lt;br /&gt;
      cuadrado : nata -&amp;gt; nat&lt;br /&gt;
   tal que (cuadrado n) es el cuadrado de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition cuadrado (n:nat) : nat := n * n.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuadrado_mult : forall n m : nat,&lt;br /&gt;
    cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                            (* n, m : nat&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            cuadrado (n * m) = &lt;br /&gt;
                                            cuadrado n * cuadrado m *)&lt;br /&gt;
  unfold cuadrado.                       (* (n * m) * (n * m) = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  rewrite producto_asociativa.           (* ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  assert (H : (n * m) * n = (n * n) * m). &lt;br /&gt;
  -                                      (* (n * m) * n = (n * n) * m) *)&lt;br /&gt;
    rewrite producto_conmutativa.        (* n * (n * m) = (n * n) * m *)&lt;br /&gt;
    apply producto_asociativa.           &lt;br /&gt;
  -                                      (* n, m : nat&lt;br /&gt;
                                            H : (n * m) * n = (n * n) * m&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite H.                           (* ((n * n) * m) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite producto_asociativa.         (* ((n * n) * m) * m = &lt;br /&gt;
                                            ((n * n) * m) * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;unfold&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.4. Definir la función&lt;br /&gt;
      const5 : nat -&amp;gt; nat&lt;br /&gt;
   tal que (const5 x) es el número 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5 (x: nat) : nat := 5.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.5. Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact prop_const5 : forall m : nat,&lt;br /&gt;
    const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.    (* m : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  const5 m + 1 = const5 (m + 1) + 1 *)&lt;br /&gt;
  simpl.       (* 6 = 6 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Expansión automática de la definición de const5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.6. Se coonsidera la siguiente definición&lt;br /&gt;
      Definition const5b (x:nat) : nat :=&lt;br /&gt;
        match x with&lt;br /&gt;
        | O   =&amp;gt; 5&lt;br /&gt;
        | S _ =&amp;gt; 5&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5b (x:nat) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | O   =&amp;gt; 5&lt;br /&gt;
  | S _ =&amp;gt; 5&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fact prop_const5b_1: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m. (* m : nat&lt;br /&gt;
               ============================&lt;br /&gt;
               const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  simpl.    (* const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Fact prop_const5b_2: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.      (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b 0 + 1 = const5b (0 + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b (S m) + 1 = const5b (S m + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Fact prop_const5b_3: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.       (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  unfold const5b. (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     match m with&lt;br /&gt;
                     | 0 | _ =&amp;gt; 5&lt;br /&gt;
                     end + 1 = match m + 1 with&lt;br /&gt;
                               | 0 | _ =&amp;gt; 5&lt;br /&gt;
                               end + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -               (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match 0 + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match S m + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.1. Se considera la siguiente definición &lt;br /&gt;
      Definition const_false (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then false&lt;br /&gt;
        else if iguales_nat n 5 then false&lt;br /&gt;
        else                         false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       const_false n = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const_false (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then false&lt;br /&gt;
  else if iguales_nat n 5 then false&lt;br /&gt;
  else                         false.&lt;br /&gt;
&lt;br /&gt;
Theorem const_false_false : forall n : nat,&lt;br /&gt;
    const_false n = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                     (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   const_false n = false *)&lt;br /&gt;
  unfold const_false.           (* (if iguales_nat n 3 then false &lt;br /&gt;
                                   else if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) =&lt;br /&gt;
                                   false *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) = false *)&lt;br /&gt;
    destruct (iguales_nat n 5). &lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.2. Se considera la siguiente definición &lt;br /&gt;
      Definition ej (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then true&lt;br /&gt;
        else if iguales_nat n 5 then true&lt;br /&gt;
        else                     false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       ej n = true -&amp;gt; esImpar n = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ej (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then true&lt;br /&gt;
  else if iguales_nat n 5 then true&lt;br /&gt;
  else                     false.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem ej_impar_a: forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                       (* n : nat&lt;br /&gt;
                                       H : ej n = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       esImpar n = true *)&lt;br /&gt;
  unfold ej in H. (* n : nat&lt;br /&gt;
                                      H : (if iguales_nat n 3&lt;br /&gt;
                                           then true&lt;br /&gt;
                                           else if iguales_nat n 5 &lt;br /&gt;
                                                then true &lt;br /&gt;
                                                else false) &lt;br /&gt;
                                          = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                                (* n : nat&lt;br /&gt;
                                      H : true = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem ej_impar : forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                             (* n : nat&lt;br /&gt;
                                             H : ej n = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  unfold ej in H.                         (* n : nat&lt;br /&gt;
                                             H : (if iguales_nat n 3&lt;br /&gt;
                                                  then true&lt;br /&gt;
                                                  else if iguales_nat n 5 &lt;br /&gt;
                                                       then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3) eqn: H3.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    apply iguales_nat_true in H3.         (* n : nat&lt;br /&gt;
                                             H3 : n = 3&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    rewrite H3.                           (* esImpar 3 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H : (if iguales_nat n 5 &lt;br /&gt;
                                                  then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    destruct (iguales_nat n 5) eqn:H5. &lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      apply iguales_nat_true in H5.       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : n = 5&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      rewrite H5.                         (* esImpar 5 = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = false&lt;br /&gt;
                                             H : false = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct e eqn: H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.1. Demostrar que desempareja y empareja son inversas; es decir,&lt;br /&gt;
        forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
          desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
          empareja xs ys = ps.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem empareja_desempareja: forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
    desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
    empareja xs ys = ps.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y ps.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ps : list (X * Y)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ps = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = ps *)&lt;br /&gt;
  induction ps as [|(x,y) ps&amp;#039; HI].&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja [ ] = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = [ ] *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja [ ] = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          H1 : [ ] = xs&lt;br /&gt;
                                          H2 : [ ] = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja [ ] [ ] = [ ] *)&lt;br /&gt;
    simpl.                             (* [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) &lt;br /&gt;
                                               -&amp;gt; empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ((x,y)::ps&amp;#039;) = (xs,ys) &lt;br /&gt;
                                           -&amp;gt; empareja xs ys = (x,y)::ps&amp;#039; *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    destruct (desempareja ps&amp;#039;) eqn: E. (* Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs: ist X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : match desempareja ps&amp;#039; with&lt;br /&gt;
                                              | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                              end = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite E in H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja (x :: l) (y :: l0) = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl.                             (* (x, y) :: empareja l l0 = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite HI.&lt;br /&gt;
    +                                  (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (x, y) :: ps&amp;#039; = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                  (*   X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (l, l0) = (l, l0)&lt;br /&gt;
 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.2. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
        f (f (f b)) = f b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem bool_tres_veces:&lt;br /&gt;
  forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
    f (f (f b)) = f b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f b.                    (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f b)) = f b *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f true)) = f true *)&lt;br /&gt;
    destruct (f true) eqn:H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      rewrite H1.                (* f true = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      destruct (f false) eqn:H2. &lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = false *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = false *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f false)) = f false *)&lt;br /&gt;
    destruct (f false) eqn:H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      destruct (f true) eqn:H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = true *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      rewrite H3.                (* f false = false *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 8. Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        iguales_nat n m = iguales_nat m n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_simetrica: forall n m : nat,&lt;br /&gt;
    iguales_nat n m = iguales_nat m n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                          (* n, m : nat&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          iguales_nat n m = iguales_nat m n *)&lt;br /&gt;
  destruct (iguales_nat n m) eqn:H1.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    apply iguales_nat_true in H1.      (* n, m : nat&lt;br /&gt;
                                          H1 : n = m&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    rewrite H1.                        (* true = iguales_nat m m *)&lt;br /&gt;
    symmetry.                          (* iguales_nat m m = true *)&lt;br /&gt;
    apply iguales_nat_refl.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = iguales_nat m n *)&lt;br /&gt;
    destruct (iguales_nat m n) eqn:H2. &lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      apply iguales_nat_true in H2.    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite H2 in H1.                (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n n = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite iguales_nat_refl in H1.  (* n, m : nat&lt;br /&gt;
                                          H1 : true = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.2. Demostrar que&lt;br /&gt;
        forall n m p : nat,&lt;br /&gt;
          iguales_nat n m = true -&amp;gt;&lt;br /&gt;
          iguales_nat m p = true -&amp;gt;&lt;br /&gt;
          iguales_nat n p = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_trans: forall n m p : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt;&lt;br /&gt;
    iguales_nat m p = true -&amp;gt;&lt;br /&gt;
    iguales_nat n p = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H1 H2.           (* n, m, p : nat&lt;br /&gt;
                                   H1 : iguales_nat n m = true&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H1. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H2. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : m = p&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  rewrite H1.                   (* iguales_nat m p = true *)&lt;br /&gt;
  rewrite H2.                   (* iguales_nat p p = true *)&lt;br /&gt;
  apply iguales_nat_refl.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.3. Definir las hipótesis sobre xs e ys para que se cumpla&lt;br /&gt;
   la propiedad &lt;br /&gt;
      desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
   y demostrarla.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* En la prueba se usará el siguiente lema *)&lt;br /&gt;
Lemma longitud_cero: forall (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = 0 -&amp;gt; xs = [].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs H.           (* X : Type&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              H : longitud xs = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs = [ ] *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              H : longitud [ ] = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    simpl in H.            (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem desempareja_empareja: forall (X : Type) (xs ys: list X),&lt;br /&gt;
    longitud xs = longitud ys -&amp;gt;&lt;br /&gt;
    desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud xs = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja xs ys) = (xs, ys) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI1]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud [ ] = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    intros ys H.                (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud [ ] = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    simpl in H.                 (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : 0 = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    symmetry in H.              (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud ys = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    apply longitud_cero in H.   (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : ys = [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [] ys) = ([], ys) *)&lt;br /&gt;
    rewrite H.                  (* desempareja (empareja [] []) = ([], []) *)&lt;br /&gt;
    simpl.                      (* ([], []) = ([], []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud [ ] -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;) -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : longitud xs&amp;#039; = longitud ys&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      apply HI1 in H1.          (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : desempareja (empareja xs&amp;#039; ys&amp;#039;) &lt;br /&gt;
                                        = (xs&amp;#039;, ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      simpl.                    (* match desempareja (empareja xs&amp;#039; ys&amp;#039;) with&lt;br /&gt;
                                   | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                   end &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      rewrite H1.               (* (x::xs&amp;#039;, y::ys&amp;#039;) = (x::xs&amp;#039;,y::ys&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.4. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
        filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
        p x = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_filtra:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
    filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
    p x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p x xs ys.           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs, ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p xs = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    simpl.                      (* [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    intros H.                   (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : [ ] = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
    destruct (p x&amp;#039;) eqn:Hx&amp;#039;. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* x&amp;#039; :: filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      rewrite H1 in Hx&amp;#039;.        (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      apply Hx&amp;#039;.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = false&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.1. Definir, por recursión, la función &lt;br /&gt;
      todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool &lt;br /&gt;
   tal que (todos p xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      todos esImpar [1;3;5;7;9]     = true&lt;br /&gt;
      todos negacion [false;false]  = true&lt;br /&gt;
      todos esPar [0;2;4;5]         = false&lt;br /&gt;
      todos (iguales_nat 5) []      = true&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then todos p xs&amp;#039;&lt;br /&gt;
             else false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (todos esImpar [1;3;5;7;9]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos negacion [false;false]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos esPar [0;2;4;5]).&lt;br /&gt;
(* = false : bool*)&lt;br /&gt;
Compute (todos (iguales_nat 5) []).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.2. Definir, por recursión, la función &lt;br /&gt;
      existe      &lt;br /&gt;
   tal que (existe p xs) se verifica si algún elemento de xs cumple&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      existe (iguales_nat 5) [0;2;3;6]           = false&lt;br /&gt;
      existe (conjuncion true) [true;true;false] = true&lt;br /&gt;
      existe esImpar [1;0;0;0;0;3]               = true&lt;br /&gt;
      existe esPar []                            = false&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint existe {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; false&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then true&lt;br /&gt;
             else existe p xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (existe (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.3. Redefinir, usando todos y negb, la función existe2 y&lt;br /&gt;
   demostrar su equivalencia con existe.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition existe2 {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  negacion (todos (fun y =&amp;gt; negacion (p y)) xs).&lt;br /&gt;
&lt;br /&gt;
Compute (existe2 (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe2 (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
Theorem equiv_existe: forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    existe p xs = existe2 p xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.               (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p xs = existe2 p xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p [ ] = existe2 p [ ] *)&lt;br /&gt;
    unfold existe2.            (* existe p [ ] = &lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                   [ ]) *)&lt;br /&gt;
    simpl.                     (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
    destruct (p x) eqn:Hx.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                  (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* true =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion true &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = false&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) &lt;br /&gt;
                                          (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion false &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      rewrite HI.              (* existe2 p xs&amp;#039; = &lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 9. Resumen de tácticas básicas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* Las tácticas básicas utilizadas hasta ahora son&lt;br /&gt;
  + apply H: &lt;br /&gt;
    + si el objetivo coincide con la hipótesis H, lo demuestra;&lt;br /&gt;
    + si H es una implicación,&lt;br /&gt;
      + si el objetivo coincide con la conclusión de H, lo sustituye por&lt;br /&gt;
        su premisa y&lt;br /&gt;
      + si el objetivo coincide con la premisa de H, lo sustituye por&lt;br /&gt;
        su conclusión.&lt;br /&gt;
&lt;br /&gt;
  + apply ... with ...: Especifica los valores de las variables que no&lt;br /&gt;
    se pueden deducir por emparejamiento.&lt;br /&gt;
&lt;br /&gt;
  + apply H1 in H2: Aplica la igualdad de la hipótesis H1 a la&lt;br /&gt;
    hipótesis H2.&lt;br /&gt;
&lt;br /&gt;
  + assert (H: P): Incluyed la demostración de la propiedad P y continúa&lt;br /&gt;
    la demostración añadiendo como premisa la propiedad P con nombre H. &lt;br /&gt;
&lt;br /&gt;
  + destruct b: Distingue dos casos según que b sea True o False.&lt;br /&gt;
&lt;br /&gt;
  + destruct n as [| n1]: Distingue dos casos según que n sea 0 o sea S n1. &lt;br /&gt;
&lt;br /&gt;
  + destruct p as [n m]: Sustituye el par p por (n,m).&lt;br /&gt;
&lt;br /&gt;
  + destruct e eqn: H: Distingue casos según el valor de la expresión&lt;br /&gt;
    e y lo añade al contexto la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + generalize dependent x: Mueve la variable x (y las que dependan de&lt;br /&gt;
    ella) del contexto a una hipótesis explícita en el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + induction n as [|n1 IHn1]: Inicia una demostración por inducción&lt;br /&gt;
    sobre n. El caso base en ~n  0~. El paso de la inducción consiste en&lt;br /&gt;
    suponer la propiedad para ~n1~ y demostrarla para ~S n1~. El nombre de la&lt;br /&gt;
    hipótesis de inducción es ~IHn1~.&lt;br /&gt;
&lt;br /&gt;
  + intros vars: Introduce las variables del cuantificador universal y,&lt;br /&gt;
    como premisas, los antecedentes de las implicaciones.&lt;br /&gt;
&lt;br /&gt;
  + inversion: Aplica qe los constructores son disjuntos e inyectivos. &lt;br /&gt;
&lt;br /&gt;
  + reflexivity: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
&lt;br /&gt;
  + rewrite H: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
&lt;br /&gt;
  + rewrite &amp;lt;-H: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
  + simpl: Simplifica el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + simpl in H: Simplifica la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + symmetry: Cambia un objetivo de la forma s = t en t = s.&lt;br /&gt;
&lt;br /&gt;
  + symmetry in H: Cambia la hipótesis H de la forma ~st~ en ~ts~.&lt;br /&gt;
&lt;br /&gt;
  + unfold f Expande la definición de la función f.&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Tactics.html More basic tactics] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=68</id>
		<title>Tema 5: Tácticas básicas de Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=68"/>
		<updated>2018-08-12T07:56:25Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se amplían las tácticas básicas estudiadas en los temas anteriores. Al final de la teoría se incluye un resumen de todas las tácticas usadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Archivo:T5_Tacticas.v|T5_Tacticas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T5: Tácticas básicas de Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T4_PolimorfismoyOS.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   5. Control de la hipótesis de inducción  &lt;br /&gt;
   6. Expansión de definiciones &lt;br /&gt;
   7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   8. Ejercicios &lt;br /&gt;
   9. Resumen de tácticas básicas &lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que &lt;br /&gt;
          n = m  -&amp;gt;&lt;br /&gt;
          [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
          [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración sin apply *)&lt;br /&gt;
Theorem artificial_1a : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  rewrite H2.           (* [n; p] = [n; p] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* Demostración con apply *)&lt;br /&gt;
Theorem artificial_1b : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que &lt;br /&gt;
      n = m  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
      [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2 : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : forall q r : nat, q = r -&amp;gt; [q; o] = [r; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  apply H2.             (* n = m *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039; en hipótesis condicionales y&lt;br /&gt;
   razonamiento hacia atrás&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Demostrar que &lt;br /&gt;
      (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
      [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2a : forall (n m : nat),&lt;br /&gt;
    (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H1 H2. (* n, m : nat&lt;br /&gt;
                       H1 : (n, n) = (m, m)&lt;br /&gt;
                       H2 : forall q r : nat, (q, q) = (r, r) -&amp;gt; [q] = [r]&lt;br /&gt;
                       ============================&lt;br /&gt;
                       [n] = [m] *)&lt;br /&gt;
  apply H2.         (* (n, n) = (m, m) *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar, sin usar simpl, que&lt;br /&gt;
      (forall n, evenb n = true -&amp;gt; oddb (S n) = true) -&amp;gt;&lt;br /&gt;
      evenb 3 = true -&amp;gt;&lt;br /&gt;
      oddb 4 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial_ex :&lt;br /&gt;
  (forall n, esPar n = true -&amp;gt; esImpar (S n) = true) -&amp;gt;&lt;br /&gt;
  esPar 3 = true -&amp;gt;&lt;br /&gt;
  esImpar 4 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 H2. (* H1 : forall n : nat, esPar n = true -&amp;gt; esImpar (S n) = true&lt;br /&gt;
                   H2 : esPar 3 = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   esImpar 4 = true *)&lt;br /&gt;
  apply H1.     (* esPar 3 = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Demostrar que &lt;br /&gt;
      true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
      iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3a: forall (n : nat),&lt;br /&gt;
    true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
    iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H. (* n : nat&lt;br /&gt;
                 H : true = iguales_nat n 5&lt;br /&gt;
                 ============================&lt;br /&gt;
                 iguales_nat (S (S n)) 7 = true *)&lt;br /&gt;
  symmetry.   (* true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  simpl.      (* true = iguales_nat n 5 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Necesidad de usar symmetry antes de apply.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar&lt;br /&gt;
      forall (xs ys : list nat), &lt;br /&gt;
       xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa2: forall (xs ys : list nat),&lt;br /&gt;
    xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.           (* xs, ys : list nat&lt;br /&gt;
                               H : xs = inversa ys&lt;br /&gt;
                               ============================&lt;br /&gt;
                               ys = inversa xs *)&lt;br /&gt;
  rewrite H.                (* ys = inversa (inversa ys) *)&lt;br /&gt;
  symmetry.                 (* inversa (inversa ys) = ys *)&lt;br /&gt;
  apply inversa_involutiva. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall (a b c d e f : nat),&lt;br /&gt;
       [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
       [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
       [a;b] = [e;f].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejemplo_con_transitiva: forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2. (* a, b, c, d, e, f : nat&lt;br /&gt;
                               H1 : [a; b] = [c; d]&lt;br /&gt;
                               H2 : [c; d] = [e; f]&lt;br /&gt;
                               ============================&lt;br /&gt;
                               [a; b] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H1.             (* [c; d] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H2.             (* [e; f] = [e; f] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem igualdad_transitiva: forall (X:Type) (n m o : X),&lt;br /&gt;
    n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X n m o H1 H2. (* X : Type&lt;br /&gt;
                           n, m, o : X&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : m = o&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.         (* m = o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.         (* o = o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El ejercicio 2.2 es una generalización del 2.1, sus&lt;br /&gt;
   demostraciones son isomorfas y se puede usar el 2.2 en la&lt;br /&gt;
   demostración del 2.1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.                  (* a, b, c, d, e, f : nat&lt;br /&gt;
                                                H1 : [a; b] = [c; d]&lt;br /&gt;
                                                H2 : [c; d] = [e; f]&lt;br /&gt;
                                                ============================&lt;br /&gt;
                                                [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with (m:=[c;d]).&lt;br /&gt;
  -                                          (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                          (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039;&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.             (* a, b, c, d, e, f : nat&lt;br /&gt;
                                           H1 : [a; b] = [c; d]&lt;br /&gt;
                                           H2 : [c; d] = [e; f]&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with [c;d].&lt;br /&gt;
  -                                     (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                     (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply ... whith ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1. Demostrar que&lt;br /&gt;
      forall (n m o p : nat),&lt;br /&gt;
        m = (menosDos o) -&amp;gt;&lt;br /&gt;
        (n + p) = m -&amp;gt;&lt;br /&gt;
        (n + p) = (menosDos o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_igualdad_transitiva: forall (n m o p : nat),&lt;br /&gt;
    m = (menosDos o) -&amp;gt;&lt;br /&gt;
    (n + p) = m -&amp;gt;&lt;br /&gt;
    (n + p) = (menosDos o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2.             (* n, m, o, p : nat&lt;br /&gt;
                                       H1 : m = menosDos o&lt;br /&gt;
                                       H2 : n + p = m&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n + p = menosDos o *)&lt;br /&gt;
  apply igualdad_transitiva with m. &lt;br /&gt;
  -                                 (* n + p = m *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
  -                                 (* m = menosDos o *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       S n = S m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inyectiva: forall (n m : nat),&lt;br /&gt;
  S n = S m -&amp;gt;&lt;br /&gt;
  n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (n m o : nat),&lt;br /&gt;
       [n; m] = [o; o] -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej1: forall (n m o : nat),&lt;br /&gt;
    [n; m] = [o; o] -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H. (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [n] = [m] *)&lt;br /&gt;
  inversion H.    (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     H1 : n = o&lt;br /&gt;
                     H2 : m = o&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [o] = [o] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       [n] = [m] -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej2: forall (n m : nat),&lt;br /&gt;
    [n] = [m] -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.         (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = m *)&lt;br /&gt;
  inversion H as [Hnm]. (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           Hnm : n = m&lt;br /&gt;
                           ============================&lt;br /&gt;
                           m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Nombramiento de las hipótesis generadas por inversión.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
        x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej3 : forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
  x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
  y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
  x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H1 H2. (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x = y *)&lt;br /&gt;
  inversion H1.               (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = y *)&lt;br /&gt;
  inversion H2.               (* xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 H4 : y = x&lt;br /&gt;
                                 H5 : xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = x *)&lt;br /&gt;
  symmetry.                   (* x = z *)&lt;br /&gt;
  apply H0.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.4. Demostrar que&lt;br /&gt;
      forall n:nat,&lt;br /&gt;
       iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_0_n: forall n:nat,&lt;br /&gt;
    iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 n = true -&amp;gt; n = 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
    intros H.           (* H : iguales_nat 0 0 = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 (S n&amp;#039;) = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    intros H.           (* n&amp;#039; : nat&lt;br /&gt;
                           H : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           S n&amp;#039; = 0 *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.5. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       S n = O -&amp;gt; 2 + 2 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej4: forall (n : nat),&lt;br /&gt;
    S n = O -&amp;gt;&lt;br /&gt;
    2 + 2 = 5.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.  (* n : nat&lt;br /&gt;
                  H : S n = 0&lt;br /&gt;
                  ============================&lt;br /&gt;
                  2 + 2 = 5 *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.6. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       false = true -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej5: forall (n m : nat),&lt;br /&gt;
    false = true -&amp;gt; [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : false = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   [n] = [m] *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
        y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        x = z.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej6 :&lt;br /&gt;
  forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
    x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
    y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
    x = z.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H. (* X : Type&lt;br /&gt;
                             x, y, z : X&lt;br /&gt;
                             xs, ys : list X&lt;br /&gt;
                             H : x :: y :: xs = [ ]&lt;br /&gt;
                             ============================&lt;br /&gt;
                             y :: xs = z :: ys -&amp;gt; x = z *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.  &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.7. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
       x = y -&amp;gt; f x = f y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem funcional: forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
    x = y -&amp;gt; f x = f y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f x y H. (* A : Type&lt;br /&gt;
                         B : Type&lt;br /&gt;
                         f : A -&amp;gt; B&lt;br /&gt;
                         x, y : A&lt;br /&gt;
                         H : x = y&lt;br /&gt;
                         ============================&lt;br /&gt;
                         f x = f y *)&lt;br /&gt;
  rewrite H.          (* f y = f y *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n m : nat) (b : bool),&lt;br /&gt;
       iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
       iguales_nat n m = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inj: forall (n m : nat) (b : bool),&lt;br /&gt;
    iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
    iguales_nat n m = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m b H. (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat (S n) (S m) = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  simpl in H.     (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat n m = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de táctica &amp;#039;simpl in ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
       true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
       true = iguales_nat (S (S n)) 7.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3&amp;#039;: forall (n : nat),&lt;br /&gt;
  (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
  true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
  true = iguales_nat (S (S n)) 7.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H1 H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat n 5&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat n 5 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H1 in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat (S (S n)) 7&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de las tácticas &amp;#039;apply H1 in H2&amp;#039; y &amp;#039;symemetry in H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n + n = m + m -&amp;gt;&lt;br /&gt;
        n = m.&lt;br /&gt;
&lt;br /&gt;
   Nota: Usar suma_s_Sm.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_n_inyectiva:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    n + n = m + m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, n + n = m + m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI]. &lt;br /&gt;
  -                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, 0 + 0 = m + m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H1.                 (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* H1 : 0 + 0 = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = S m *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, S n&amp;#039; + S n&amp;#039; = m + m &lt;br /&gt;
                                                    -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H2.                 (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H2.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H2.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : n&amp;#039; + S n&amp;#039; = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (n&amp;#039; + n&amp;#039;) = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H0.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : m + S m = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H0.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : m + m = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      apply HI in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- H1.             (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Control de la hipótesis de inducción  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª intento *)&lt;br /&gt;
Theorem doble_inyectiva_FAILED : forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.             (* n, m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros H.             (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble (S n&amp;#039;) = doble m -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros H.             (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva: forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H.           (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble (S n&amp;#039;) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, S (S (doble n&amp;#039;)) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H.           (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.           (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.        (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la estrategia de generalización.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_true : forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat 0 m = true &lt;br /&gt;
                                              -&amp;gt; 0 = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 (S m&amp;#039;) = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat (S n&amp;#039;) m = true&lt;br /&gt;
                                                   -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) 0 = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                        -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) (S m&amp;#039;) = true &lt;br /&gt;
                                   -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* iguales_nat n&amp;#039; m&amp;#039; = true -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : iguales_nat n&amp;#039; m&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply HIn&amp;#039; in H.          (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      rewrite H.                (* S m&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
    &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2a: forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI].&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                      (* doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros H.                   (* n : nat&lt;br /&gt;
                                   H : doble n = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                           (* H : doble 0 = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.               (* n&amp;#039; : nat&lt;br /&gt;
                                   H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble (S m&amp;#039;) -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
&lt;br /&gt;
    intros H.                   (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.               (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble (S n&amp;#039;) = doble m&amp;#039; -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.          (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2 : forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.               (* n, m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  generalize dependent n.   (* m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI]. &lt;br /&gt;
  -                         (*  &lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                  (* forall n : nat, doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros n H.             (* n : nat&lt;br /&gt;
                               H : doble n = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                       (* H : doble 0 = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                       (* n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.           (* n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                         (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble (S m&amp;#039;) &lt;br /&gt;
                                               -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
    intros n H.             (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n : nat&lt;br /&gt;
                               H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.      (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.             (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.          (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;generalize dependent n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Demostrar que&lt;br /&gt;
      forall x y : id,&lt;br /&gt;
       iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_true: forall x y : id,&lt;br /&gt;
  iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [m] [n].           (* m, n : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id (Id m) (Id n) = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  simpl.                    (* iguales_nat m n = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  intros H.                 (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
  assert (H&amp;#039; : m = n).&lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               m = n *)&lt;br /&gt;
    apply iguales_nat_true. (* iguales_nat m n = true *)&lt;br /&gt;
    apply H. &lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               H&amp;#039; : m = n&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
    rewrite H&amp;#039;.             (* Id n = Id n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar, por inducción sobre l,&lt;br /&gt;
      forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
        longitud xs = n -&amp;gt;&lt;br /&gt;
        nthOpcional xs n = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nthOpcional_None: forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = n -&amp;gt;&lt;br /&gt;
    nthOpcional xs n = None.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n X xs.               (* n : nat&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  generalize dependent n.       (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud [] = n -&amp;gt; nthOpcional [] n = None *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = n -&amp;gt; &lt;br /&gt;
                                   nthOpcional (x :: xs&amp;#039;) n = None *)&lt;br /&gt;
    destruct n as [|n&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = 0 -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) (S n&amp;#039;) = None *)&lt;br /&gt;
      simpl.                    (* S (longitud xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                   nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      apply HI.                 (* longitud xs&amp;#039; = n&amp;#039; *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  H1 : longitud xs&amp;#039; = n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs&amp;#039; = longitud xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 6. Expansión de definiciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.1. Definir la función&lt;br /&gt;
      cuadrado : nata -&amp;gt; nat&lt;br /&gt;
   tal que (cuadrado n) es el cuadrado de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition cuadrado (n:nat) : nat := n * n.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuadrado_mult : forall n m : nat,&lt;br /&gt;
    cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                            (* n, m : nat&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            cuadrado (n * m) = &lt;br /&gt;
                                            cuadrado n * cuadrado m *)&lt;br /&gt;
  unfold cuadrado.                       (* (n * m) * (n * m) = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  rewrite producto_asociativa.           (* ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  assert (H : (n * m) * n = (n * n) * m). &lt;br /&gt;
  -                                      (* (n * m) * n = (n * n) * m) *)&lt;br /&gt;
    rewrite producto_conmutativa.        (* n * (n * m) = (n * n) * m *)&lt;br /&gt;
    apply producto_asociativa.           &lt;br /&gt;
  -                                      (* n, m : nat&lt;br /&gt;
                                            H : (n * m) * n = (n * n) * m&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite H.                           (* ((n * n) * m) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite producto_asociativa.         (* ((n * n) * m) * m = &lt;br /&gt;
                                            ((n * n) * m) * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;unfold&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.4. Definir la función&lt;br /&gt;
      const5 : nat -&amp;gt; nat&lt;br /&gt;
   tal que (const5 x) es el número 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5 (x: nat) : nat := 5.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.5. Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact prop_const5 : forall m : nat,&lt;br /&gt;
    const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.    (* m : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  const5 m + 1 = const5 (m + 1) + 1 *)&lt;br /&gt;
  simpl.       (* 6 = 6 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Expansión automática de la definición de const5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.6. Se coonsidera la siguiente definición&lt;br /&gt;
      Definition const5b (x:nat) : nat :=&lt;br /&gt;
        match x with&lt;br /&gt;
        | O   =&amp;gt; 5&lt;br /&gt;
        | S _ =&amp;gt; 5&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5b (x:nat) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | O   =&amp;gt; 5&lt;br /&gt;
  | S _ =&amp;gt; 5&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fact prop_const5b_1: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m. (* m : nat&lt;br /&gt;
               ============================&lt;br /&gt;
               const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  simpl.    (* const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Fact prop_const5b_2: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.      (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b 0 + 1 = const5b (0 + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b (S m) + 1 = const5b (S m + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Fact prop_const5b_3: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.       (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  unfold const5b. (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     match m with&lt;br /&gt;
                     | 0 | _ =&amp;gt; 5&lt;br /&gt;
                     end + 1 = match m + 1 with&lt;br /&gt;
                               | 0 | _ =&amp;gt; 5&lt;br /&gt;
                               end + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -               (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match 0 + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match S m + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.1. Se considera la siguiente definición &lt;br /&gt;
      Definition const_false (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then false&lt;br /&gt;
        else if iguales_nat n 5 then false&lt;br /&gt;
        else                         false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       const_false n = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const_false (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then false&lt;br /&gt;
  else if iguales_nat n 5 then false&lt;br /&gt;
  else                         false.&lt;br /&gt;
&lt;br /&gt;
Theorem const_false_false : forall n : nat,&lt;br /&gt;
    const_false n = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                     (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   const_false n = false *)&lt;br /&gt;
  unfold const_false.           (* (if iguales_nat n 3 then false &lt;br /&gt;
                                   else if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) =&lt;br /&gt;
                                   false *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) = false *)&lt;br /&gt;
    destruct (iguales_nat n 5). &lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.2. Se considera la siguiente definición &lt;br /&gt;
      Definition ej (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then true&lt;br /&gt;
        else if iguales_nat n 5 then true&lt;br /&gt;
        else                     false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       ej n = true -&amp;gt; esImpar n = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ej (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then true&lt;br /&gt;
  else if iguales_nat n 5 then true&lt;br /&gt;
  else                     false.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem ej_impar_a: forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                       (* n : nat&lt;br /&gt;
                                       H : ej n = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       esImpar n = true *)&lt;br /&gt;
  unfold ej in H. (* n : nat&lt;br /&gt;
                                      H : (if iguales_nat n 3&lt;br /&gt;
                                           then true&lt;br /&gt;
                                           else if iguales_nat n 5 &lt;br /&gt;
                                                then true &lt;br /&gt;
                                                else false) &lt;br /&gt;
                                          = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                                (* n : nat&lt;br /&gt;
                                      H : true = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem ej_impar : forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                             (* n : nat&lt;br /&gt;
                                             H : ej n = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  unfold ej in H.                         (* n : nat&lt;br /&gt;
                                             H : (if iguales_nat n 3&lt;br /&gt;
                                                  then true&lt;br /&gt;
                                                  else if iguales_nat n 5 &lt;br /&gt;
                                                       then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3) eqn: H3.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    apply iguales_nat_true in H3.         (* n : nat&lt;br /&gt;
                                             H3 : n = 3&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    rewrite H3.                           (* esImpar 3 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H : (if iguales_nat n 5 &lt;br /&gt;
                                                  then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    destruct (iguales_nat n 5) eqn:H5. &lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      apply iguales_nat_true in H5.       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : n = 5&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      rewrite H5.                         (* esImpar 5 = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = false&lt;br /&gt;
                                             H : false = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct e eqn: H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.1. Demostrar que desempareja y empareja son inversas; es decir,&lt;br /&gt;
        forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
          desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
          empareja xs ys = ps.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem empareja_desempareja: forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
    desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
    empareja xs ys = ps.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y ps.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ps : list (X * Y)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ps = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = ps *)&lt;br /&gt;
  induction ps as [|(x,y) ps&amp;#039; HI].&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja [ ] = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = [ ] *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja [ ] = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          H1 : [ ] = xs&lt;br /&gt;
                                          H2 : [ ] = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja [ ] [ ] = [ ] *)&lt;br /&gt;
    simpl.                             (* [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) &lt;br /&gt;
                                               -&amp;gt; empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ((x,y)::ps&amp;#039;) = (xs,ys) &lt;br /&gt;
                                           -&amp;gt; empareja xs ys = (x,y)::ps&amp;#039; *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    destruct (desempareja ps&amp;#039;) eqn: E. (* Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs: ist X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : match desempareja ps&amp;#039; with&lt;br /&gt;
                                              | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                              end = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite E in H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja (x :: l) (y :: l0) = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl.                             (* (x, y) :: empareja l l0 = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite HI.&lt;br /&gt;
    +                                  (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (x, y) :: ps&amp;#039; = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                  (*   X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (l, l0) = (l, l0)&lt;br /&gt;
 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.2. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
        f (f (f b)) = f b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem bool_tres_veces:&lt;br /&gt;
  forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
    f (f (f b)) = f b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f b.                    (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f b)) = f b *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f true)) = f true *)&lt;br /&gt;
    destruct (f true) eqn:H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      rewrite H1.                (* f true = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      destruct (f false) eqn:H2. &lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = false *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = false *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f false)) = f false *)&lt;br /&gt;
    destruct (f false) eqn:H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      destruct (f true) eqn:H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = true *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      rewrite H3.                (* f false = false *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 8. Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        iguales_nat n m = iguales_nat m n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_simetrica: forall n m : nat,&lt;br /&gt;
    iguales_nat n m = iguales_nat m n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                          (* n, m : nat&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          iguales_nat n m = iguales_nat m n *)&lt;br /&gt;
  destruct (iguales_nat n m) eqn:H1.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    apply iguales_nat_true in H1.      (* n, m : nat&lt;br /&gt;
                                          H1 : n = m&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    rewrite H1.                        (* true = iguales_nat m m *)&lt;br /&gt;
    symmetry.                          (* iguales_nat m m = true *)&lt;br /&gt;
    apply iguales_nat_refl.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = iguales_nat m n *)&lt;br /&gt;
    destruct (iguales_nat m n) eqn:H2. &lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      apply iguales_nat_true in H2.    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite H2 in H1.                (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n n = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite iguales_nat_refl in H1.  (* n, m : nat&lt;br /&gt;
                                          H1 : true = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.2. Demostrar que&lt;br /&gt;
        forall n m p : nat,&lt;br /&gt;
          iguales_nat n m = true -&amp;gt;&lt;br /&gt;
          iguales_nat m p = true -&amp;gt;&lt;br /&gt;
          iguales_nat n p = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_trans: forall n m p : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt;&lt;br /&gt;
    iguales_nat m p = true -&amp;gt;&lt;br /&gt;
    iguales_nat n p = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H1 H2.           (* n, m, p : nat&lt;br /&gt;
                                   H1 : iguales_nat n m = true&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H1. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H2. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : m = p&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  rewrite H1.                   (* iguales_nat m p = true *)&lt;br /&gt;
  rewrite H2.                   (* iguales_nat p p = true *)&lt;br /&gt;
  apply iguales_nat_refl.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.3. Definir las hipótesis sobre xs e ys para que se cumpla&lt;br /&gt;
   la propiedad &lt;br /&gt;
      desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
   y demostrarla.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* En la prueba se usará el siguiente lema *)&lt;br /&gt;
Lemma longitud_cero: forall (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = 0 -&amp;gt; xs = [].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs H.           (* X : Type&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              H : longitud xs = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs = [ ] *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              H : longitud [ ] = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    simpl in H.            (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem desempareja_empareja: forall (X : Type) (xs ys: list X),&lt;br /&gt;
    longitud xs = longitud ys -&amp;gt;&lt;br /&gt;
    desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud xs = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja xs ys) = (xs, ys) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI1]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud [ ] = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    intros ys H.                (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud [ ] = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    simpl in H.                 (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : 0 = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    symmetry in H.              (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud ys = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    apply longitud_cero in H.   (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : ys = [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [] ys) = ([], ys) *)&lt;br /&gt;
    rewrite H.                  (* desempareja (empareja [] []) = ([], []) *)&lt;br /&gt;
    simpl.                      (* ([], []) = ([], []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud [ ] -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;) -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : longitud xs&amp;#039; = longitud ys&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      apply HI1 in H1.          (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : desempareja (empareja xs&amp;#039; ys&amp;#039;) &lt;br /&gt;
                                        = (xs&amp;#039;, ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      simpl.                    (* match desempareja (empareja xs&amp;#039; ys&amp;#039;) with&lt;br /&gt;
                                   | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                   end &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      rewrite H1.               (* (x::xs&amp;#039;, y::ys&amp;#039;) = (x::xs&amp;#039;,y::ys&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.4. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
        filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
        p x = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_filtra:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
    filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
    p x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p x xs ys.           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs, ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p xs = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    simpl.                      (* [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    intros H.                   (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : [ ] = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
    destruct (p x&amp;#039;) eqn:Hx&amp;#039;. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* x&amp;#039; :: filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      rewrite H1 in Hx&amp;#039;.        (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      apply Hx&amp;#039;.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = false&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.1. Definir, por recursión, la función &lt;br /&gt;
      todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool &lt;br /&gt;
   tal que (todos p xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      todos esImpar [1;3;5;7;9]     = true&lt;br /&gt;
      todos negacion [false;false]  = true&lt;br /&gt;
      todos esPar [0;2;4;5]         = false&lt;br /&gt;
      todos (iguales_nat 5) []      = true&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then todos p xs&amp;#039;&lt;br /&gt;
             else false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (todos esImpar [1;3;5;7;9]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos negacion [false;false]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos esPar [0;2;4;5]).&lt;br /&gt;
(* = false : bool*)&lt;br /&gt;
Compute (todos (iguales_nat 5) []).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.2. Definir, por recursión, la función &lt;br /&gt;
      existe      &lt;br /&gt;
   tal que (existe p xs) se verifica si algún elemento de xs cumple&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      existe (iguales_nat 5) [0;2;3;6]           = false&lt;br /&gt;
      existe (conjuncion true) [true;true;false] = true&lt;br /&gt;
      existe esImpar [1;0;0;0;0;3]               = true&lt;br /&gt;
      existe esPar []                            = false&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint existe {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; false&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then true&lt;br /&gt;
             else existe p xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (existe (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.3. Redefinir, usando todos y negb, la función existe2 y&lt;br /&gt;
   demostrar su equivalencia con existe.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition existe2 {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  negacion (todos (fun y =&amp;gt; negacion (p y)) xs).&lt;br /&gt;
&lt;br /&gt;
Compute (existe2 (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe2 (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
Theorem equiv_existe: forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    existe p xs = existe2 p xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.               (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p xs = existe2 p xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p [ ] = existe2 p [ ] *)&lt;br /&gt;
    unfold existe2.            (* existe p [ ] = &lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                   [ ]) *)&lt;br /&gt;
    simpl.                     (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
    destruct (p x) eqn:Hx.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                  (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* true =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion true &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = false&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) &lt;br /&gt;
                                          (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion false &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      rewrite HI.              (* existe2 p xs&amp;#039; = &lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 9. Resumen de tácticas básicas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* Las tácticas básicas utilizadas hasta ahora son&lt;br /&gt;
  + apply H: &lt;br /&gt;
    + si el objetivo coincide con la hipótesis H, lo demuestra;&lt;br /&gt;
    + si H es una implicación,&lt;br /&gt;
      + si el objetivo coincide con la conclusión de H, lo sustituye por&lt;br /&gt;
        su premisa y&lt;br /&gt;
      + si el objetivo coincide con la premisa de H, lo sustituye por&lt;br /&gt;
        su conclusión.&lt;br /&gt;
&lt;br /&gt;
  + apply ... with ...: Especifica los valores de las variables que no&lt;br /&gt;
    se pueden deducir por emparejamiento.&lt;br /&gt;
&lt;br /&gt;
  + apply H1 in H2: Aplica la igualdad de la hipótesis H1 a la&lt;br /&gt;
    hipótesis H2.&lt;br /&gt;
&lt;br /&gt;
  + assert (H: P): Incluyed la demostración de la propiedad P y continúa&lt;br /&gt;
    la demostración añadiendo como premisa la propiedad P con nombre H. &lt;br /&gt;
&lt;br /&gt;
  + destruct b: Distingue dos casos según que b sea True o False.&lt;br /&gt;
&lt;br /&gt;
  + destruct n as [| n1]: Distingue dos casos según que n sea 0 o sea S n1. &lt;br /&gt;
&lt;br /&gt;
  + destruct p as [n m]: Sustituye el par p por (n,m).&lt;br /&gt;
&lt;br /&gt;
  + destruct e eqn: H: Distingue casos según el valor de la expresión&lt;br /&gt;
    e y lo añade al contexto la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + generalize dependent x: Mueve la variable x (y las que dependan de&lt;br /&gt;
    ella) del contexto a una hipótesis explícita en el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + induction n as [|n1 IHn1]: Inicia una demostración por inducción&lt;br /&gt;
    sobre n. El caso base en ~n  0~. El paso de la inducción consiste en&lt;br /&gt;
    suponer la propiedad para ~n1~ y demostrarla para ~S n1~. El nombre de la&lt;br /&gt;
    hipótesis de inducción es ~IHn1~.&lt;br /&gt;
&lt;br /&gt;
  + intros vars: Introduce las variables del cuantificador universal y,&lt;br /&gt;
    como premisas, los antecedentes de las implicaciones.&lt;br /&gt;
&lt;br /&gt;
  + inversion: Aplica qe los constructores son disjuntos e inyectivos. &lt;br /&gt;
&lt;br /&gt;
  + reflexivity: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
&lt;br /&gt;
  + rewrite H: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
&lt;br /&gt;
  + rewrite &amp;lt;-H: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
  + simpl: Simplifica el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + simpl in H: Simplifica la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + symmetry: Cambia un objetivo de la forma s = t en t = s.&lt;br /&gt;
&lt;br /&gt;
  + symmetry in H: Cambia la hipótesis H de la forma ~st~ en ~ts~.&lt;br /&gt;
&lt;br /&gt;
  + unfold f Expande la definición de la función f.&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Tactics.html More basic tactics] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T5_Tacticas.v&amp;diff=67</id>
		<title>Archivo:T5 Tacticas.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T5_Tacticas.v&amp;diff=67"/>
		<updated>2018-08-12T07:49:06Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=66</id>
		<title>Tema 5: Tácticas básicas de Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_5:_T%C3%A1cticas_b%C3%A1sicas_de_Coq&amp;diff=66"/>
		<updated>2018-08-12T07:48:45Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página creada con «En este tema se amplían las tácticas básicas estudiadas en los temas anteriores. Al final de la teoría se incluye un resumen de todas las tácticas usadas hasta ahora.…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se amplían las tácticas básicas estudiadas en los temas anteriores. Al final de la teoría se incluye un resumen de todas las tácticas usadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T5_Tacticas.v|T5_Tacticas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T5: Tácticas básicas de Coq *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
Require Export T4_PolimorfismoyOS.&lt;br /&gt;
&lt;br /&gt;
(* El contenido del tema es&lt;br /&gt;
   1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   5. Control de la hipótesis de inducción  &lt;br /&gt;
   6. Expansión de definiciones &lt;br /&gt;
   7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   8. Ejercicios &lt;br /&gt;
   9. Resumen de tácticas básicas &lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. La táctica &amp;#039;apply&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que &lt;br /&gt;
          n = m  -&amp;gt;&lt;br /&gt;
          [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
          [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración sin apply *)&lt;br /&gt;
Theorem artificial_1a : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  rewrite H2.           (* [n; p] = [n; p] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* Demostración con apply *)&lt;br /&gt;
Theorem artificial_1b : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    [n;o] = [n;p] -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : [n; o] = [n; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  rewrite &amp;lt;- H1.         (* [n; o] = [n; p] *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que &lt;br /&gt;
      n = m  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
      [n;o] = [m;p].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2 : forall (n m o p : nat),&lt;br /&gt;
    n = m  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), q = r -&amp;gt; [q;o] = [r;p]) -&amp;gt;&lt;br /&gt;
    [n;o] = [m;p].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2. (* n, m, o, p : nat&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : forall q r : nat, q = r -&amp;gt; [q; o] = [r; p]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           [n; o] = [m; p] *)&lt;br /&gt;
  apply H2.             (* n = m *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply&amp;#039; en hipótesis condicionales y&lt;br /&gt;
   razonamiento hacia atrás&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Demostrar que &lt;br /&gt;
      (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
      (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
      [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial2a : forall (n m : nat),&lt;br /&gt;
    (n,n) = (m,m)  -&amp;gt;&lt;br /&gt;
    (forall (q r : nat), (q,q) = (r,r) -&amp;gt; [q] = [r]) -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H1 H2. (* n, m : nat&lt;br /&gt;
                       H1 : (n, n) = (m, m)&lt;br /&gt;
                       H2 : forall q r : nat, (q, q) = (r, r) -&amp;gt; [q] = [r]&lt;br /&gt;
                       ============================&lt;br /&gt;
                       [n] = [m] *)&lt;br /&gt;
  apply H2.         (* (n, n) = (m, m) *)&lt;br /&gt;
  apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar, sin usar simpl, que&lt;br /&gt;
      (forall n, evenb n = true -&amp;gt; oddb (S n) = true) -&amp;gt;&lt;br /&gt;
      evenb 3 = true -&amp;gt;&lt;br /&gt;
      oddb 4 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial_ex :&lt;br /&gt;
  (forall n, esPar n = true -&amp;gt; esImpar (S n) = true) -&amp;gt;&lt;br /&gt;
  esPar 3 = true -&amp;gt;&lt;br /&gt;
  esImpar 4 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros H1 H2. (* H1 : forall n : nat, esPar n = true -&amp;gt; esImpar (S n) = true&lt;br /&gt;
                   H2 : esPar 3 = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   esImpar 4 = true *)&lt;br /&gt;
  apply H1.     (* esPar 3 = true *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Demostrar que &lt;br /&gt;
      true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
      iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3a: forall (n : nat),&lt;br /&gt;
    true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
    iguales_nat (S (S n)) 7 = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H. (* n : nat&lt;br /&gt;
                 H : true = iguales_nat n 5&lt;br /&gt;
                 ============================&lt;br /&gt;
                 iguales_nat (S (S n)) 7 = true *)&lt;br /&gt;
  symmetry.   (* true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  simpl.      (* true = iguales_nat n 5 *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Necesidad de usar symmetry antes de apply.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar&lt;br /&gt;
      forall (xs ys : list nat), &lt;br /&gt;
       xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa2: forall (xs ys : list nat),&lt;br /&gt;
    xs = inversa ys -&amp;gt; ys = inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.           (* xs, ys : list nat&lt;br /&gt;
                               H : xs = inversa ys&lt;br /&gt;
                               ============================&lt;br /&gt;
                               ys = inversa xs *)&lt;br /&gt;
  rewrite H.                (* ys = inversa (inversa ys) *)&lt;br /&gt;
  symmetry.                 (* inversa (inversa ys) = ys *)&lt;br /&gt;
  apply inversa_involutiva. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. La táctica &amp;#039;apply ... with ...&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall (a b c d e f : nat),&lt;br /&gt;
       [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
       [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
       [a;b] = [e;f].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejemplo_con_transitiva: forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2. (* a, b, c, d, e, f : nat&lt;br /&gt;
                               H1 : [a; b] = [c; d]&lt;br /&gt;
                               H2 : [c; d] = [e; f]&lt;br /&gt;
                               ============================&lt;br /&gt;
                               [a; b] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H1.             (* [c; d] = [e; f] *)&lt;br /&gt;
  rewrite -&amp;gt; H2.             (* [e; f] = [e; f] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem igualdad_transitiva: forall (X:Type) (n m o : X),&lt;br /&gt;
    n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X n m o H1 H2. (* X : Type&lt;br /&gt;
                           n, m, o : X&lt;br /&gt;
                           H1 : n = m&lt;br /&gt;
                           H2 : m = o&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.         (* m = o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.         (* o = o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. El ejercicio 2.2 es una generalización del 2.1, sus&lt;br /&gt;
   demostraciones son isomorfas y se puede usar el 2.2 en la&lt;br /&gt;
   demostración del 2.1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3. Demostrar que&lt;br /&gt;
      forall (X : Type) (n m o : X),&lt;br /&gt;
       n = m -&amp;gt; m = o -&amp;gt; n = o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.                  (* a, b, c, d, e, f : nat&lt;br /&gt;
                                                H1 : [a; b] = [c; d]&lt;br /&gt;
                                                H2 : [c; d] = [e; f]&lt;br /&gt;
                                                ============================&lt;br /&gt;
                                                [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with (m:=[c;d]).&lt;br /&gt;
  -                                          (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                          (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Example ejemplo_con_transitiva&amp;#039;&amp;#039; : forall (a b c d e f : nat),&lt;br /&gt;
    [a;b] = [c;d] -&amp;gt;&lt;br /&gt;
    [c;d] = [e;f] -&amp;gt;&lt;br /&gt;
    [a;b] = [e;f].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros a b c d e f H1 H2.             (* a, b, c, d, e, f : nat&lt;br /&gt;
                                           H1 : [a; b] = [c; d]&lt;br /&gt;
                                           H2 : [c; d] = [e; f]&lt;br /&gt;
                                           ============================&lt;br /&gt;
                                           [a; b] = [e; f] *)&lt;br /&gt;
  apply igualdad_transitiva with [c;d].&lt;br /&gt;
  -                                     (* [a; b] = [c; d] *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
  -                                     (* [c; d] = [e; f] *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;apply ... whith ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.1. Demostrar que&lt;br /&gt;
      forall (n m o p : nat),&lt;br /&gt;
        m = (menosDos o) -&amp;gt;&lt;br /&gt;
        (n + p) = m -&amp;gt;&lt;br /&gt;
        (n + p) = (menosDos o).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example ejercicio_igualdad_transitiva: forall (n m o p : nat),&lt;br /&gt;
    m = (menosDos o) -&amp;gt;&lt;br /&gt;
    (n + p) = m -&amp;gt;&lt;br /&gt;
    (n + p) = (menosDos o).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o p H1 H2.             (* n, m, o, p : nat&lt;br /&gt;
                                       H1 : m = menosDos o&lt;br /&gt;
                                       H2 : n + p = m&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       n + p = menosDos o *)&lt;br /&gt;
  apply igualdad_transitiva with m. &lt;br /&gt;
  -                                 (* n + p = m *)&lt;br /&gt;
    apply H2.&lt;br /&gt;
  -                                 (* m = menosDos o *)&lt;br /&gt;
    apply H1.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. La táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       S n = S m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inyectiva: forall (n m : nat),&lt;br /&gt;
  S n = S m -&amp;gt;&lt;br /&gt;
  n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m *)&lt;br /&gt;
  inversion H.  (* n, m : nat&lt;br /&gt;
                   H : S n = S m&lt;br /&gt;
                   H1 : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;inversion&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      forall (n m o : nat),&lt;br /&gt;
       [n; m] = [o; o] -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej1: forall (n m o : nat),&lt;br /&gt;
    [n; m] = [o; o] -&amp;gt;&lt;br /&gt;
    [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H. (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [n] = [m] *)&lt;br /&gt;
  inversion H.    (* n, m, o : nat&lt;br /&gt;
                     H : [n; m] = [o; o]&lt;br /&gt;
                     H1 : n = o&lt;br /&gt;
                     H2 : m = o&lt;br /&gt;
                     ============================&lt;br /&gt;
                     [o] = [o] *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       [n] = [m] -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej2: forall (n m : nat),&lt;br /&gt;
    [n] = [m] -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H.         (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           ============================&lt;br /&gt;
                           n = m *)&lt;br /&gt;
  inversion H as [Hnm]. (* n, m : nat&lt;br /&gt;
                           H : [n] = [m]&lt;br /&gt;
                           Hnm : n = m&lt;br /&gt;
                           ============================&lt;br /&gt;
                           m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Nombramiento de las hipótesis generadas por inversión.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
        x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej3 : forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
  x :: y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
  y :: xs = x :: ys -&amp;gt;&lt;br /&gt;
  x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H1 H2. (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 x = y *)&lt;br /&gt;
  inversion H1.               (* X : Type&lt;br /&gt;
                                 x, y, z : X&lt;br /&gt;
                                 xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = y *)&lt;br /&gt;
  inversion H2.               (* xs, ys : list X&lt;br /&gt;
                                 H1 : x :: y :: xs = z :: ys&lt;br /&gt;
                                 H2 : y :: xs = x :: ys&lt;br /&gt;
                                 H0 : x = z&lt;br /&gt;
                                 H3 : y :: xs = ys&lt;br /&gt;
                                 H4 : y = x&lt;br /&gt;
                                 H5 : xs = ys&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 z = x *)&lt;br /&gt;
  symmetry.                   (* x = z *)&lt;br /&gt;
  apply H0.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.4. Demostrar que&lt;br /&gt;
      forall n:nat,&lt;br /&gt;
       iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_0_n: forall n:nat,&lt;br /&gt;
    iguales_nat 0 n = true -&amp;gt; n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 n = true -&amp;gt; n = 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
    intros H.           (* H : iguales_nat 0 0 = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           iguales_nat 0 (S n&amp;#039;) = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                           false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
    intros H.           (* n&amp;#039; : nat&lt;br /&gt;
                           H : false = true&lt;br /&gt;
                           ============================&lt;br /&gt;
                           S n&amp;#039; = 0 *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.5. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       S n = O -&amp;gt; 2 + 2 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej4: forall (n : nat),&lt;br /&gt;
    S n = O -&amp;gt;&lt;br /&gt;
    2 + 2 = 5.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.  (* n : nat&lt;br /&gt;
                  H : S n = 0&lt;br /&gt;
                  ============================&lt;br /&gt;
                  2 + 2 = 5 *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.6. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
       false = true -&amp;gt; [n] = [m].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversion_ej5: forall (n m : nat),&lt;br /&gt;
    false = true -&amp;gt; [n] = [m].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n, m : nat&lt;br /&gt;
                   H : false = true&lt;br /&gt;
                   ============================&lt;br /&gt;
                   [n] = [m] *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
        x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
        y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
        x = z.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example inversion_ej6 :&lt;br /&gt;
  forall (X : Type) (x y z : X) (xs ys : list X),&lt;br /&gt;
    x :: y :: xs = [] -&amp;gt;&lt;br /&gt;
    y :: xs = z :: ys -&amp;gt;&lt;br /&gt;
    x = z.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X x y z xs ys H. (* X : Type&lt;br /&gt;
                             x, y, z : X&lt;br /&gt;
                             xs, ys : list X&lt;br /&gt;
                             H : x :: y :: xs = [ ]&lt;br /&gt;
                             ============================&lt;br /&gt;
                             y :: xs = z :: ys -&amp;gt; x = z *)&lt;br /&gt;
  inversion H.&lt;br /&gt;
Qed.  &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.7. Demostrar que&lt;br /&gt;
      forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
       x = y -&amp;gt; f x = f y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem funcional: forall (A B : Type) (f: A -&amp;gt; B) (x y: A),&lt;br /&gt;
    x = y -&amp;gt; f x = f y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A B f x y H. (* A : Type&lt;br /&gt;
                         B : Type&lt;br /&gt;
                         f : A -&amp;gt; B&lt;br /&gt;
                         x, y : A&lt;br /&gt;
                         H : x = y&lt;br /&gt;
                         ============================&lt;br /&gt;
                         f x = f y *)&lt;br /&gt;
  rewrite H.          (* f y = f y *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Uso de tácticas sobre las hipótesis&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n m : nat) (b : bool),&lt;br /&gt;
       iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
       iguales_nat n m = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_inj: forall (n m : nat) (b : bool),&lt;br /&gt;
    iguales_nat (S n) (S m) = b  -&amp;gt;&lt;br /&gt;
    iguales_nat n m = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m b H. (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat (S n) (S m) = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  simpl in H.     (* n, m : nat&lt;br /&gt;
                     b : bool&lt;br /&gt;
                     H : iguales_nat n m = b&lt;br /&gt;
                     ============================&lt;br /&gt;
                     iguales_nat n m = b *)&lt;br /&gt;
  apply H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de táctica &amp;#039;simpl in ...&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Demostrar que&lt;br /&gt;
      forall (n : nat),&lt;br /&gt;
       (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
       true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
       true = iguales_nat (S (S n)) 7.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem artificial3&amp;#039;: forall (n : nat),&lt;br /&gt;
  (iguales_nat n 5 = true -&amp;gt; iguales_nat (S (S n)) 7 = true) -&amp;gt;&lt;br /&gt;
  true = iguales_nat n 5  -&amp;gt;&lt;br /&gt;
  true = iguales_nat (S (S n)) 7.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H1 H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat n 5&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat n 5 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H1 in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  symmetry in H2. (* n : nat&lt;br /&gt;
                     H1 : iguales_nat n 5 = true -&amp;gt; &lt;br /&gt;
                          iguales_nat (S (S n)) 7 = true&lt;br /&gt;
                     H2 : true = iguales_nat (S (S n)) 7&lt;br /&gt;
                     ============================&lt;br /&gt;
                     true = iguales_nat (S (S n)) 7 *)&lt;br /&gt;
  apply H2.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de las tácticas &amp;#039;apply H1 in H2&amp;#039; y &amp;#039;symemetry in H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        n + n = m + m -&amp;gt;&lt;br /&gt;
        n = m.&lt;br /&gt;
&lt;br /&gt;
   Nota: Usar suma_s_Sm.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_n_inyectiva:&lt;br /&gt;
  forall n m : nat,&lt;br /&gt;
    n + n = m + m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, n + n = m + m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI]. &lt;br /&gt;
  -                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, 0 + 0 = m + m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H1.                 (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* H1 : 0 + 0 = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* m : nat&lt;br /&gt;
                                    H1 : 0 + 0 = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    0 = S m *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
  -                              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    forall m : nat, S n&amp;#039; + S n&amp;#039; = m + m &lt;br /&gt;
                                                    -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H2.                 (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = m *)&lt;br /&gt;
    destruct m.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = 0 + 0&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H2.&lt;br /&gt;
    +                            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H2.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : n&amp;#039; + S n&amp;#039; = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (n&amp;#039; + n&amp;#039;) = m + S m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H0.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : m + S m = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- suma_n_Sm in H0. (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      inversion H0.              (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : m + m = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      symmetry in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; + n&amp;#039; = m + m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      apply HI in H1.            (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S m *)&lt;br /&gt;
      rewrite &amp;lt;- H1.             (* n&amp;#039; : nat&lt;br /&gt;
                                    HI : forall m : nat, n&amp;#039; + n&amp;#039; = m + m &lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                    m : nat&lt;br /&gt;
                                    H2 : S n&amp;#039; + S n&amp;#039; = S m + S m&lt;br /&gt;
                                    H0 : S (m + m) = S (n&amp;#039; + n&amp;#039;)&lt;br /&gt;
                                    H1 : n&amp;#039; = m&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Control de la hipótesis de inducción  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª intento *)&lt;br /&gt;
Theorem doble_inyectiva_FAILED : forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.             (* n, m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* m : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros H.             (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble (S n&amp;#039;) = doble m -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros H.             (* n&amp;#039;, m : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble 0 -&amp;gt; n&amp;#039; = 0&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                             HI : doble n&amp;#039; = doble (S m&amp;#039;) -&amp;gt; n&amp;#039; = S m&amp;#039;&lt;br /&gt;
                             H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva: forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.               (* n : nat&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction n as [| n&amp;#039; HI].&lt;br /&gt;
  -                       (* &lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, 0 = doble m -&amp;gt; 0 = m *)&lt;br /&gt;
    intros m H.           (* m : nat&lt;br /&gt;
                             H : 0 = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;].&lt;br /&gt;
    +                     (* H : 0 = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                     (* m&amp;#039; : nat&lt;br /&gt;
                             H : 0 = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                       (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             forall m : nat, doble (S n&amp;#039;) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    simpl.                (* forall m : nat, S (S (doble n&amp;#039;)) = doble m &lt;br /&gt;
                                             -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    intros m H.           (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble m&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = m *)&lt;br /&gt;
    destruct m as [| m&amp;#039;]. &lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.         (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                     (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             ============================&lt;br /&gt;
                             S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.    (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.           (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.        (* n&amp;#039; : nat&lt;br /&gt;
                             HI : forall m : nat, doble n&amp;#039; = doble m -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                             m&amp;#039; : nat&lt;br /&gt;
                             H : S (S (doble n&amp;#039;)) = doble (S m&amp;#039;)&lt;br /&gt;
                             H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                             ============================&lt;br /&gt;
                             doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la estrategia de generalización.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
        iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_true : forall n m : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt; n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat 0 m = true &lt;br /&gt;
                                              -&amp;gt; 0 = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 0 = true -&amp;gt; 0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat 0 (S m&amp;#039;) = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; 0 = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat 0 m&amp;#039; = true -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall m : nat, iguales_nat (S n&amp;#039;) m = true&lt;br /&gt;
                                                   -&amp;gt; S n&amp;#039; = m *)&lt;br /&gt;
    induction m as [|m&amp;#039; HIm&amp;#039;].&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) 0 = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl.                    (* false = true -&amp;gt; S n&amp;#039; = 0 *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                        -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   H : false = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat (S n&amp;#039;) (S m&amp;#039;) = true &lt;br /&gt;
                                   -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      simpl.                    (* iguales_nat n&amp;#039; m&amp;#039; = true -&amp;gt; S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      intros H.                 (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : iguales_nat n&amp;#039; m&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply HIn&amp;#039; in H.          (* n&amp;#039; : nat&lt;br /&gt;
                                   HIn&amp;#039; : forall m:nat, iguales_nat n&amp;#039; m = true&lt;br /&gt;
                                                         -&amp;gt; n&amp;#039; = m&lt;br /&gt;
                                   m&amp;#039; : nat&lt;br /&gt;
                                   HIm&amp;#039; : iguales_nat (S n&amp;#039;) m&amp;#039; = true &lt;br /&gt;
                                          -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      rewrite H.                (* S m&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
    &lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       doble n = doble m -&amp;gt;&lt;br /&gt;
       n = m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2a: forall n m : nat,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI].&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                      (* doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros H.                   (* n : nat&lt;br /&gt;
                                   H : doble n = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                           (* H : doble 0 = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n&amp;#039; : nat&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.               (* n&amp;#039; : nat&lt;br /&gt;
                                   H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                             (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   doble n = doble (S m&amp;#039;) -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
&lt;br /&gt;
    intros H.                   (* n, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                                   H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                           (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.               (* m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble 0 = doble m&amp;#039; -&amp;gt; 0 = m&amp;#039;&lt;br /&gt;
                                   H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* n&amp;#039;, m&amp;#039; : nat&lt;br /&gt;
                                   HI : doble (S n&amp;#039;) = doble m&amp;#039; -&amp;gt; S n&amp;#039; = m&amp;#039;&lt;br /&gt;
                                   H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.          (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem doble_inyectiva_2 : forall n m,&lt;br /&gt;
    doble n = doble m -&amp;gt;&lt;br /&gt;
    n = m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.               (* n, m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  generalize dependent n.   (* m : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble m -&amp;gt; n = m *)&lt;br /&gt;
  induction m as [| m&amp;#039; HI]. &lt;br /&gt;
  -                         (*  &lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    simpl.                  (* forall n : nat, doble n = 0 -&amp;gt; n = 0 *)&lt;br /&gt;
    intros n H.             (* n : nat&lt;br /&gt;
                               H : doble n = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = 0 *)&lt;br /&gt;
    destruct n as [| n&amp;#039;].&lt;br /&gt;
    +                       (* H : doble 0 = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = 0 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                       (* n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      simpl in H.           (* n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = 0&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = 0 *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
  -                         (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               forall n : nat, doble n = doble (S m&amp;#039;) &lt;br /&gt;
                                               -&amp;gt; n = S m&amp;#039; *)&lt;br /&gt;
    intros n H.             (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n : nat&lt;br /&gt;
                               H : doble n = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               n = S m&amp;#039; *)&lt;br /&gt;
    destruct n as [| n&amp;#039;]. &lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : doble 0 = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               H : 0 = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               0 = S m&amp;#039; *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                       (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : doble (S n&amp;#039;) = doble (S m&amp;#039;)&lt;br /&gt;
                               ============================&lt;br /&gt;
                               S n&amp;#039; = S m&amp;#039; *)&lt;br /&gt;
      apply funcional.      (* n&amp;#039; = m&amp;#039; *)&lt;br /&gt;
      apply HI.             (* doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      simpl in H.           (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble m&amp;#039; *)&lt;br /&gt;
      inversion H.          (* m&amp;#039; : nat&lt;br /&gt;
                               HI : forall n : nat, doble n = doble m&amp;#039; -&amp;gt; n = m&amp;#039;&lt;br /&gt;
                               n&amp;#039; : nat&lt;br /&gt;
                               H : S (S (doble n&amp;#039;)) = S (S (doble m&amp;#039;))&lt;br /&gt;
                               H1 : doble n&amp;#039; = doble m&amp;#039;&lt;br /&gt;
                               ============================&lt;br /&gt;
                               doble n&amp;#039; = doble n&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;generalize dependent n&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Demostrar que&lt;br /&gt;
      forall x y : id,&lt;br /&gt;
       iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_true: forall x y : id,&lt;br /&gt;
  iguales_id x y = true -&amp;gt; x = y.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [m] [n].           (* m, n : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id (Id m) (Id n) = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  simpl.                    (* iguales_nat m n = true -&amp;gt; Id m = Id n *)&lt;br /&gt;
  intros H.                 (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
  assert (H&amp;#039; : m = n).&lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               ============================&lt;br /&gt;
                               m = n *)&lt;br /&gt;
    apply iguales_nat_true. (* iguales_nat m n = true *)&lt;br /&gt;
    apply H. &lt;br /&gt;
  -                         (* m, n : nat&lt;br /&gt;
                               H : iguales_nat m n = true&lt;br /&gt;
                               H&amp;#039; : m = n&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Id m = Id n *)&lt;br /&gt;
    rewrite H&amp;#039;.             (* Id n = Id n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar, por inducción sobre l,&lt;br /&gt;
      forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
        longitud xs = n -&amp;gt;&lt;br /&gt;
        nthOpcional xs n = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nthOpcional_None: forall (n : nat) (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = n -&amp;gt;&lt;br /&gt;
    nthOpcional xs n = None.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n X xs.               (* n : nat&lt;br /&gt;
                                  X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  generalize dependent n.       (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud xs = n -&amp;gt; nthOpcional xs n = None *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud [] = n -&amp;gt; nthOpcional [] n = None *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  forall n : nat, &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = n -&amp;gt; &lt;br /&gt;
                                   nthOpcional (x :: xs&amp;#039;) n = None *)&lt;br /&gt;
    destruct n as [|n&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = 0 -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) 0 = None *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                  nthOpcional (x :: xs&amp;#039;) (S n&amp;#039;) = None *)&lt;br /&gt;
      simpl.                    (* S (longitud xs&amp;#039;) = S n&amp;#039; -&amp;gt; &lt;br /&gt;
                                   nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  nthOpcional xs&amp;#039; n&amp;#039; = None *)&lt;br /&gt;
      apply HI.                 (* longitud xs&amp;#039; = n&amp;#039; *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : forall n : nat, &lt;br /&gt;
                                        longitud xs&amp;#039; = n -&amp;gt; &lt;br /&gt;
                                        nthOpcional xs&amp;#039; n = None&lt;br /&gt;
                                  n&amp;#039; : nat&lt;br /&gt;
                                  H : S (longitud xs&amp;#039;) = S n&amp;#039;&lt;br /&gt;
                                  H1 : longitud xs&amp;#039; = n&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud xs&amp;#039; = longitud xs&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 6. Expansión de definiciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.1. Definir la función&lt;br /&gt;
      cuadrado : nata -&amp;gt; nat&lt;br /&gt;
   tal que (cuadrado n) es el cuadrado de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition cuadrado (n:nat) : nat := n * n.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.2. Demostrar que&lt;br /&gt;
      forall n m : nat,&lt;br /&gt;
       cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma cuadrado_mult : forall n m : nat,&lt;br /&gt;
    cuadrado (n * m) = cuadrado n * cuadrado m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                            (* n, m : nat&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            cuadrado (n * m) = &lt;br /&gt;
                                            cuadrado n * cuadrado m *)&lt;br /&gt;
  unfold cuadrado.                       (* (n * m) * (n * m) = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  rewrite producto_asociativa.           (* ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
  assert (H : (n * m) * n = (n * n) * m). &lt;br /&gt;
  -                                      (* (n * m) * n = (n * n) * m) *)&lt;br /&gt;
    rewrite producto_conmutativa.        (* n * (n * m) = (n * n) * m *)&lt;br /&gt;
    apply producto_asociativa.           &lt;br /&gt;
  -                                      (* n, m : nat&lt;br /&gt;
                                            H : (n * m) * n = (n * n) * m&lt;br /&gt;
                                            ============================&lt;br /&gt;
                                            ((n * m) * n) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite H.                           (* ((n * n) * m) * m = &lt;br /&gt;
                                            (n * n) * (m * m) *)&lt;br /&gt;
    rewrite producto_asociativa.         (* ((n * n) * m) * m = &lt;br /&gt;
                                            ((n * n) * m) * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;unfold&amp;#039;&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.4. Definir la función&lt;br /&gt;
      const5 : nat -&amp;gt; nat&lt;br /&gt;
   tal que (const5 x) es el número 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5 (x: nat) : nat := 5.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.5. Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fact prop_const5 : forall m : nat,&lt;br /&gt;
    const5 m + 1 = const5 (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.    (* m : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  const5 m + 1 = const5 (m + 1) + 1 *)&lt;br /&gt;
  simpl.       (* 6 = 6 *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Expansión automática de la definición de const5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 6.6. Se coonsidera la siguiente definición&lt;br /&gt;
      Definition const5b (x:nat) : nat :=&lt;br /&gt;
        match x with&lt;br /&gt;
        | O   =&amp;gt; 5&lt;br /&gt;
        | S _ =&amp;gt; 5&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall m : nat,&lt;br /&gt;
       const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const5b (x:nat) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | O   =&amp;gt; 5&lt;br /&gt;
  | S _ =&amp;gt; 5&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Fact prop_const5b_1: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m. (* m : nat&lt;br /&gt;
               ============================&lt;br /&gt;
               const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  simpl.    (* const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Fact prop_const5b_2: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.      (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b 0 + 1 = const5b (0 + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* m : nat&lt;br /&gt;
                    ============================&lt;br /&gt;
                    const5b (S m) + 1 = const5b (S m + 1) + 1 *)&lt;br /&gt;
    simpl.       (* 6 = 6 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Fact prop_const5b_3: forall m : nat,&lt;br /&gt;
    const5b m + 1 = const5b (m + 1) + 1.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros m.       (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     const5b m + 1 = const5b (m + 1) + 1 *)&lt;br /&gt;
  unfold const5b. (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     match m with&lt;br /&gt;
                     | 0 | _ =&amp;gt; 5&lt;br /&gt;
                     end + 1 = match m + 1 with&lt;br /&gt;
                               | 0 | _ =&amp;gt; 5&lt;br /&gt;
                               end + 1 *)&lt;br /&gt;
  destruct m.&lt;br /&gt;
  -               (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match 0 + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -               (* m : nat&lt;br /&gt;
                     ============================&lt;br /&gt;
                     5 + 1 = match S m + 1 with&lt;br /&gt;
                             | 0 | _ =&amp;gt; 5&lt;br /&gt;
                             end + 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 7. Uso de &amp;#039;destruct&amp;#039; sobre expresiones compuestas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.1. Se considera la siguiente definición &lt;br /&gt;
      Definition const_false (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then false&lt;br /&gt;
        else if iguales_nat n 5 then false&lt;br /&gt;
        else                         false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       const_false n = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition const_false (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then false&lt;br /&gt;
  else if iguales_nat n 5 then false&lt;br /&gt;
  else                         false.&lt;br /&gt;
&lt;br /&gt;
Theorem const_false_false : forall n : nat,&lt;br /&gt;
    const_false n = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                     (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   const_false n = false *)&lt;br /&gt;
  unfold const_false.           (* (if iguales_nat n 3 then false &lt;br /&gt;
                                   else if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) =&lt;br /&gt;
                                   false *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (if iguales_nat n 5 then false &lt;br /&gt;
                                   else false) = false *)&lt;br /&gt;
    destruct (iguales_nat n 5). &lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 7.2. Se considera la siguiente definición &lt;br /&gt;
      Definition ej (n : nat) : bool :=&lt;br /&gt;
        if      iguales_nat n 3 then true&lt;br /&gt;
        else if iguales_nat n 5 then true&lt;br /&gt;
        else                     false.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que&lt;br /&gt;
      forall n : nat,&lt;br /&gt;
       ej n = true -&amp;gt; esImpar n = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ej (n : nat) : bool :=&lt;br /&gt;
  if      iguales_nat n 3 then true&lt;br /&gt;
  else if iguales_nat n 5 then true&lt;br /&gt;
  else                     false.&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem ej_impar_a: forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                       (* n : nat&lt;br /&gt;
                                       H : ej n = true&lt;br /&gt;
                                       ============================&lt;br /&gt;
                                       esImpar n = true *)&lt;br /&gt;
  unfold ej in H. (* n : nat&lt;br /&gt;
                                      H : (if iguales_nat n 3&lt;br /&gt;
                                           then true&lt;br /&gt;
                                           else if iguales_nat n 5 &lt;br /&gt;
                                                then true &lt;br /&gt;
                                                else false) &lt;br /&gt;
                                          = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3).&lt;br /&gt;
  -                                (* n : nat&lt;br /&gt;
                                      H : true = true&lt;br /&gt;
                                      ============================&lt;br /&gt;
                                      esImpar n = true *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem ej_impar : forall n : nat,&lt;br /&gt;
    ej n = true -&amp;gt;&lt;br /&gt;
    esImpar n = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n H.                             (* n : nat&lt;br /&gt;
                                             H : ej n = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  unfold ej in H.                         (* n : nat&lt;br /&gt;
                                             H : (if iguales_nat n 3&lt;br /&gt;
                                                  then true&lt;br /&gt;
                                                  else if iguales_nat n 5 &lt;br /&gt;
                                                       then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
  destruct (iguales_nat n 3) eqn: H3.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    apply iguales_nat_true in H3.         (* n : nat&lt;br /&gt;
                                             H3 : n = 3&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    rewrite H3.                           (* esImpar 3 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H : (if iguales_nat n 5 &lt;br /&gt;
                                                  then true else false) &lt;br /&gt;
                                                 = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
    destruct (iguales_nat n 5) eqn:H5. &lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = true&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      apply iguales_nat_true in H5.       (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : n = 5&lt;br /&gt;
                                             H : true = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      rewrite H5.                         (* esImpar 5 = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                     (* n : nat&lt;br /&gt;
                                             H3 : iguales_nat n 3 = false&lt;br /&gt;
                                             H5 : iguales_nat n 5 = false&lt;br /&gt;
                                             H : false = true&lt;br /&gt;
                                             ============================&lt;br /&gt;
                                             esImpar n = true *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Uso de la táctica &amp;#039;destruct e eqn: H&amp;#039;.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.1. Demostrar que desempareja y empareja son inversas; es decir,&lt;br /&gt;
        forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
          desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
          empareja xs ys = ps.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem empareja_desempareja: forall X Y (ps : list (X * Y)) xs ys,&lt;br /&gt;
    desempareja ps = (xs, ys) -&amp;gt;&lt;br /&gt;
    empareja xs ys = ps.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y ps.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ps : list (X * Y)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ps = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = ps *)&lt;br /&gt;
  induction ps as [|(x,y) ps&amp;#039; HI].&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja [ ] = (xs, ys) -&amp;gt; &lt;br /&gt;
                                           empareja xs ys = [ ] *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja [ ] = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = [ ] *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : ([ ], [ ]) = (xs, ys)&lt;br /&gt;
                                          H1 : [ ] = xs&lt;br /&gt;
                                          H2 : [ ] = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja [ ] [ ] = [ ] *)&lt;br /&gt;
    simpl.                             (* [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) &lt;br /&gt;
                                               -&amp;gt; empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          forall (xs : list X) (ys : list Y),&lt;br /&gt;
                                           desempareja ((x,y)::ps&amp;#039;) = (xs,ys) &lt;br /&gt;
                                           -&amp;gt; empareja xs ys = (x,y)::ps&amp;#039; *)&lt;br /&gt;
    intros xs ys H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               desempareja ps&amp;#039; = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    destruct (desempareja ps&amp;#039;) eqn: E. (* Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : desempareja ((x,y)::ps&amp;#039;) = (xs,ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl in H.                        (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs: ist X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : match desempareja ps&amp;#039; with&lt;br /&gt;
                                              | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                              end = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite E in H.                    (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja xs ys = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    inversion H.                       (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          empareja (x :: l) (y :: l0) = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    simpl.                             (* (x, y) :: empareja l l0 = &lt;br /&gt;
                                          (x, y) :: ps&amp;#039; *)&lt;br /&gt;
    rewrite HI.&lt;br /&gt;
    +                                  (* X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt;&lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (x, y) :: ps&amp;#039; = (x, y) :: ps&amp;#039; *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                                  (*   X : Type&lt;br /&gt;
                                          Y : Type&lt;br /&gt;
                                          x : X&lt;br /&gt;
                                          y : Y&lt;br /&gt;
                                          ps&amp;#039; : list (X * Y)&lt;br /&gt;
                                          l : list X&lt;br /&gt;
                                          l0 : list Y&lt;br /&gt;
                                          E : desempareja ps&amp;#039; = (l, l0)&lt;br /&gt;
                                          HI : forall (xs:list X) (ys:list Y),&lt;br /&gt;
                                               (l, l0) = (xs, ys) -&amp;gt; &lt;br /&gt;
                                               empareja xs ys = ps&amp;#039;&lt;br /&gt;
                                          xs : list X&lt;br /&gt;
                                          ys : list Y&lt;br /&gt;
                                          H : (x :: l, y :: l0) = (xs, ys)&lt;br /&gt;
                                          H1 : x :: l = xs&lt;br /&gt;
                                          H2 : y :: l0 = ys&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          (l, l0) = (l, l0)&lt;br /&gt;
 *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 7.2. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
        f (f (f b)) = f b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem bool_tres_veces:&lt;br /&gt;
  forall (f : bool -&amp;gt; bool) (b : bool),&lt;br /&gt;
    f (f (f b)) = f b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f b.                    (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    b : bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f b)) = f b *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f true)) = f true *)&lt;br /&gt;
    destruct (f true) eqn:H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      rewrite H1.                (* f true = true *)&lt;br /&gt;
      apply H1.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      destruct (f false) eqn:H2. &lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = false *)&lt;br /&gt;
        apply H1.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H1 : f true = false&lt;br /&gt;
                                    H2 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = false *)&lt;br /&gt;
        apply H2.&lt;br /&gt;
  -                              (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f (f false)) = f false *)&lt;br /&gt;
    destruct (f false) eqn:H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f true) = true *)&lt;br /&gt;
      destruct (f true) eqn:H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = true&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f true = true *)&lt;br /&gt;
        apply H4.&lt;br /&gt;
      *                          (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = true&lt;br /&gt;
                                    H4 : f true = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f false = true *)&lt;br /&gt;
        apply H3.&lt;br /&gt;
    +                            (* f : bool -&amp;gt; bool&lt;br /&gt;
                                    H3 : f false = false&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    f (f false) = false *)&lt;br /&gt;
      rewrite H3.                (* f false = false *)&lt;br /&gt;
      apply H3.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 8. Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.1. Demostrar que&lt;br /&gt;
      forall (n m : nat),&lt;br /&gt;
        iguales_nat n m = iguales_nat m n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_simetrica: forall n m : nat,&lt;br /&gt;
    iguales_nat n m = iguales_nat m n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                          (* n, m : nat&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          iguales_nat n m = iguales_nat m n *)&lt;br /&gt;
  destruct (iguales_nat n m) eqn:H1.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    apply iguales_nat_true in H1.      (* n, m : nat&lt;br /&gt;
                                          H1 : n = m&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          true = iguales_nat m n *)&lt;br /&gt;
    rewrite H1.                        (* true = iguales_nat m m *)&lt;br /&gt;
    symmetry.                          (* iguales_nat m m = true *)&lt;br /&gt;
    apply iguales_nat_refl.&lt;br /&gt;
  -                                    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = iguales_nat m n *)&lt;br /&gt;
    destruct (iguales_nat m n) eqn:H2. &lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = true&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      apply iguales_nat_true in H2.    (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite H2 in H1.                (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n n = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      rewrite iguales_nat_refl in H1.  (* n, m : nat&lt;br /&gt;
                                          H1 : true = false&lt;br /&gt;
                                          H2 : m = n&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = true *)&lt;br /&gt;
      inversion H1.&lt;br /&gt;
    +                                  (* n, m : nat&lt;br /&gt;
                                          H1 : iguales_nat n m = false&lt;br /&gt;
                                          H2 : iguales_nat m n = false&lt;br /&gt;
                                          ============================&lt;br /&gt;
                                          false = false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.2. Demostrar que&lt;br /&gt;
        forall n m p : nat,&lt;br /&gt;
          iguales_nat n m = true -&amp;gt;&lt;br /&gt;
          iguales_nat m p = true -&amp;gt;&lt;br /&gt;
          iguales_nat n p = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_nat_trans: forall n m p : nat,&lt;br /&gt;
    iguales_nat n m = true -&amp;gt;&lt;br /&gt;
    iguales_nat m p = true -&amp;gt;&lt;br /&gt;
    iguales_nat n p = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H1 H2.           (* n, m, p : nat&lt;br /&gt;
                                   H1 : iguales_nat n m = true&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H1. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : iguales_nat m p = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  apply iguales_nat_true in H2. (* n, m, p : nat&lt;br /&gt;
                                   H1 : n = m&lt;br /&gt;
                                   H2 : m = p&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   iguales_nat n p = true *)&lt;br /&gt;
  rewrite H1.                   (* iguales_nat m p = true *)&lt;br /&gt;
  rewrite H2.                   (* iguales_nat p p = true *)&lt;br /&gt;
  apply iguales_nat_refl.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.3. Definir las hipótesis sobre xs e ys para que se cumpla&lt;br /&gt;
   la propiedad &lt;br /&gt;
      desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
   y demostrarla.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* En la prueba se usará el siguiente lema *)&lt;br /&gt;
Lemma longitud_cero: forall (X : Type) (xs : list X),&lt;br /&gt;
    longitud xs = 0 -&amp;gt; xs = [].&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs H.           (* X : Type&lt;br /&gt;
                              xs : list X&lt;br /&gt;
                              H : longitud xs = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs = [ ] *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              H : longitud [ ] = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : longitud (x :: xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    simpl in H.            (* X : Type&lt;br /&gt;
                              x : X&lt;br /&gt;
                              xs&amp;#039; : list X&lt;br /&gt;
                              H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                              ============================&lt;br /&gt;
                              x :: xs&amp;#039; = [ ] *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem desempareja_empareja: forall (X : Type) (xs ys: list X),&lt;br /&gt;
    longitud xs = longitud ys -&amp;gt;&lt;br /&gt;
    desempareja (empareja xs ys) = (xs,ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                  (* X : Type&lt;br /&gt;
                                   xs : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud xs = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja xs ys) = (xs, ys) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI1]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud [ ] = longitud ys -&amp;gt; &lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    intros ys H.                (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud [ ] = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    simpl in H.                 (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : 0 = longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    symmetry in H.              (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : longitud ys = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [ ] ys) = ([ ], ys) *)&lt;br /&gt;
    apply longitud_cero in H.   (* X : Type&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : ys = [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja [] ys) = ([], ys) *)&lt;br /&gt;
    rewrite H.                  (* desempareja (empareja [] []) = ([], []) *)&lt;br /&gt;
    simpl.                      (* ([], []) = ([], []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   forall ys : list X,&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    intros ys.                  (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud ys -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) ys) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, ys) *)&lt;br /&gt;
    destruct ys as [|y ys&amp;#039;].&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud [ ] -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud [ ]&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      simpl in H.               (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   H : S (longitud xs&amp;#039;) = 0&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x :: xs&amp;#039;) [ ]) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, [ ]) *)&lt;br /&gt;
      inversion H.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;) -&amp;gt;&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : longitud xs&amp;#039; = longitud ys&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      apply HI1 in H1.          (* X : Type&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs&amp;#039; : list X&lt;br /&gt;
                                   HI1 : forall ys : list X,&lt;br /&gt;
                                         longitud xs&amp;#039; = longitud ys -&amp;gt;&lt;br /&gt;
                                         desempareja (empareja xs&amp;#039; ys) &lt;br /&gt;
                                         = (xs&amp;#039;, ys)&lt;br /&gt;
                                   y : X&lt;br /&gt;
                                   ys&amp;#039; : list X&lt;br /&gt;
                                   H : longitud (x :: xs&amp;#039;) = longitud (y :: ys&amp;#039;)&lt;br /&gt;
                                   H1 : desempareja (empareja xs&amp;#039; ys&amp;#039;) &lt;br /&gt;
                                        = (xs&amp;#039;, ys&amp;#039;)&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   desempareja (empareja (x::xs&amp;#039;) (y::ys&amp;#039;)) &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      simpl.                    (* match desempareja (empareja xs&amp;#039; ys&amp;#039;) with&lt;br /&gt;
                                   | (xs, ys) =&amp;gt; (x :: xs, y :: ys)&lt;br /&gt;
                                   end &lt;br /&gt;
                                   = (x :: xs&amp;#039;, y :: ys&amp;#039;) *)&lt;br /&gt;
      rewrite H1.               (* (x::xs&amp;#039;, y::ys&amp;#039;) = (x::xs&amp;#039;,y::ys&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.4. Demostrar que&lt;br /&gt;
      forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
        filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
        p x = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem prop_filtra:&lt;br /&gt;
  forall (X : Type) (p : X -&amp;gt; bool) (x : X) (xs ys : list X),&lt;br /&gt;
    filtra p xs = x :: ys -&amp;gt;&lt;br /&gt;
    p x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p x xs ys.           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   xs, ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p xs = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    simpl.                      (* [ ] = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
    intros H.                   (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x : X&lt;br /&gt;
                                   ys : list X&lt;br /&gt;
                                   H : [ ] = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
    inversion H.&lt;br /&gt;
  -                             (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
    destruct (p x&amp;#039;) eqn:Hx&amp;#039;. &lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* x&amp;#039; :: filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      intros H.                 (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      inversion H.              (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      rewrite H1 in Hx&amp;#039;.        (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x = true&lt;br /&gt;
                                   H : x&amp;#039; :: filtra p xs&amp;#039; = x :: ys&lt;br /&gt;
                                   H1 : x&amp;#039; = x&lt;br /&gt;
                                   H2 : filtra p xs&amp;#039; = ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   p x = true *)&lt;br /&gt;
      apply Hx&amp;#039;.&lt;br /&gt;
    +                           (* X : Type&lt;br /&gt;
                                   p : X -&amp;gt; bool&lt;br /&gt;
                                   x, x&amp;#039; : X&lt;br /&gt;
                                   xs&amp;#039;, ys : list X&lt;br /&gt;
                                   HI : filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true&lt;br /&gt;
                                   Hx&amp;#039; : p x&amp;#039; = false&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   filtra p (x&amp;#039;::xs&amp;#039;) = x::ys -&amp;gt; p x = true *)&lt;br /&gt;
      simpl.                    (* (if p x&amp;#039; then x&amp;#039; :: filtra p xs&amp;#039; &lt;br /&gt;
                                            else filtra p xs&amp;#039;) &lt;br /&gt;
                                   = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      rewrite Hx&amp;#039;.              (* filtra p xs&amp;#039; = x :: ys -&amp;gt; p x = true *)&lt;br /&gt;
      apply HI.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.1. Definir, por recursión, la función &lt;br /&gt;
      todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool &lt;br /&gt;
   tal que (todos p xs) se verifica si todos los elementos de xs cumplen&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      todos esImpar [1;3;5;7;9]     = true&lt;br /&gt;
      todos negacion [false;false]  = true&lt;br /&gt;
      todos esPar [0;2;4;5]         = false&lt;br /&gt;
      todos (iguales_nat 5) []      = true&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint todos {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then todos p xs&amp;#039;&lt;br /&gt;
             else false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (todos esImpar [1;3;5;7;9]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos negacion [false;false]).&lt;br /&gt;
(* = true : bool*)&lt;br /&gt;
Compute (todos esPar [0;2;4;5]).&lt;br /&gt;
(* = false : bool*)&lt;br /&gt;
Compute (todos (iguales_nat 5) []).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.2. Definir, por recursión, la función &lt;br /&gt;
      existe      &lt;br /&gt;
   tal que (existe p xs) se verifica si algún elemento de xs cumple&lt;br /&gt;
   p. Por ejemplo, &lt;br /&gt;
      existe (iguales_nat 5) [0;2;3;6]           = false&lt;br /&gt;
      existe (conjuncion true) [true;true;false] = true&lt;br /&gt;
      existe esImpar [1;0;0;0;0;3]               = true&lt;br /&gt;
      existe esPar []                            = false&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint existe {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; false&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
             then true&lt;br /&gt;
             else existe p xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (existe (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 8.5.3. Redefinir, usando todos y negb, la función existe2 y&lt;br /&gt;
   demostrar su equivalencia con existe.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition existe2 {X : Type} (p : X -&amp;gt; bool) (xs : list X) : bool :=&lt;br /&gt;
  negacion (todos (fun y =&amp;gt; negacion (p y)) xs).&lt;br /&gt;
&lt;br /&gt;
Compute (existe2 (iguales_nat 5) [0;2;3;6]).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
Compute (existe2 (conjuncion true) [true;true;false]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esImpar [1;0;0;0;0;3]).&lt;br /&gt;
(* = true : bool *)&lt;br /&gt;
Compute (existe2 esPar []).&lt;br /&gt;
(* = false : bool *)&lt;br /&gt;
&lt;br /&gt;
Theorem equiv_existe: forall (X : Type) (p : X -&amp;gt; bool) (xs : list X),&lt;br /&gt;
    existe p xs = existe2 p xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X p xs.               (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p xs = existe2 p xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p [ ] = existe2 p [ ] *)&lt;br /&gt;
    unfold existe2.            (* existe p [ ] = &lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                   [ ]) *)&lt;br /&gt;
    simpl.                     (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
    destruct (p x) eqn:Hx.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion (todos (fun y : X =&amp;gt; negacion (p y))&lt;br /&gt;
                                                  (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* true =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion true &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* X : Type&lt;br /&gt;
                                  p : X -&amp;gt; bool&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : existe p xs&amp;#039; = existe2 p xs&amp;#039;&lt;br /&gt;
                                  Hx : p x = false&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  existe p (x :: xs&amp;#039;) = existe2 p (x :: xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* existe p (x :: xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) &lt;br /&gt;
                                          (x :: xs&amp;#039;)) *)&lt;br /&gt;
      simpl.                   (* (if p x then true else existe p xs&amp;#039;) =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion (p x) &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      rewrite Hx.              (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion&lt;br /&gt;
                                   (if negacion false &lt;br /&gt;
                                    then todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;&lt;br /&gt;
                                    else false) *)&lt;br /&gt;
      simpl.                   (* existe p xs&amp;#039; =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      rewrite HI.              (* existe2 p xs&amp;#039; = &lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      unfold existe2.          (* negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) =&lt;br /&gt;
                                  negacion &lt;br /&gt;
                                   (todos (fun y : X =&amp;gt; negacion (p y)) xs&amp;#039;) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 9. Resumen de tácticas básicas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* Las tácticas básicas utilizadas hasta ahora son&lt;br /&gt;
  + apply H: &lt;br /&gt;
    + si el objetivo coincide con la hipótesis H, lo demuestra;&lt;br /&gt;
    + si H es una implicación,&lt;br /&gt;
      + si el objetivo coincide con la conclusión de H, lo sustituye por&lt;br /&gt;
        su premisa y&lt;br /&gt;
      + si el objetivo coincide con la premisa de H, lo sustituye por&lt;br /&gt;
        su conclusión.&lt;br /&gt;
&lt;br /&gt;
  + apply ... with ...: Especifica los valores de las variables que no&lt;br /&gt;
    se pueden deducir por emparejamiento.&lt;br /&gt;
&lt;br /&gt;
  + apply H1 in H2: Aplica la igualdad de la hipótesis H1 a la&lt;br /&gt;
    hipótesis H2.&lt;br /&gt;
&lt;br /&gt;
  + assert (H: P): Incluyed la demostración de la propiedad P y continúa&lt;br /&gt;
    la demostración añadiendo como premisa la propiedad P con nombre H. &lt;br /&gt;
&lt;br /&gt;
  + destruct b: Distingue dos casos según que b sea True o False.&lt;br /&gt;
&lt;br /&gt;
  + destruct n as [| n1]: Distingue dos casos según que n sea 0 o sea S n1. &lt;br /&gt;
&lt;br /&gt;
  + destruct p as [n m]: Sustituye el par p por (n,m).&lt;br /&gt;
&lt;br /&gt;
  + destruct e eqn: H: Distingue casos según el valor de la expresión&lt;br /&gt;
    e y lo añade al contexto la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + generalize dependent x: Mueve la variable x (y las que dependan de&lt;br /&gt;
    ella) del contexto a una hipótesis explícita en el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + induction n as [|n1 IHn1]: Inicia una demostración por inducción&lt;br /&gt;
    sobre n. El caso base en ~n  0~. El paso de la inducción consiste en&lt;br /&gt;
    suponer la propiedad para ~n1~ y demostrarla para ~S n1~. El nombre de la&lt;br /&gt;
    hipótesis de inducción es ~IHn1~.&lt;br /&gt;
&lt;br /&gt;
  + intros vars: Introduce las variables del cuantificador universal y,&lt;br /&gt;
    como premisas, los antecedentes de las implicaciones.&lt;br /&gt;
&lt;br /&gt;
  + inversion: Aplica qe los constructores son disjuntos e inyectivos. &lt;br /&gt;
&lt;br /&gt;
  + reflexivity: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
&lt;br /&gt;
  + rewrite H: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
&lt;br /&gt;
  + rewrite &amp;lt;-H: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
  + simpl: Simplifica el objetivo.&lt;br /&gt;
&lt;br /&gt;
  + simpl in H: Simplifica la hipótesis H.&lt;br /&gt;
&lt;br /&gt;
  + symmetry: Cambia un objetivo de la forma s = t en t = s.&lt;br /&gt;
&lt;br /&gt;
  + symmetry in H: Cambia la hipótesis H de la forma ~st~ en ~ts~.&lt;br /&gt;
&lt;br /&gt;
  + unfold f Expande la definición de la función f.&lt;br /&gt;
 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Tactics.html More basic tactics] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=65</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=65"/>
		<updated>2018-08-12T07:48:19Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;br /&gt;
* [[Tema 4: Polimorfismo y funciones de orden superior en Coq]].&lt;br /&gt;
* [[Tema 5: Tácticas básicas de Coq]].&lt;br /&gt;
&lt;br /&gt;
=== Código ===&lt;br /&gt;
&lt;br /&gt;
El código correspondiente se encuentra en [https://github.com/jaalonso/DAOconCoq GitHub].&lt;br /&gt;
&lt;br /&gt;
=== Libro ===&lt;br /&gt;
&lt;br /&gt;
Todos los temas están recopilados en el libro [https://github.com/jaalonso/DAOconCoq/raw/master/texto/DAOconCoq.pdf Demostración asistida por ordenador con Coq].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T4_PolimorfismoyOS.v&amp;diff=64</id>
		<title>Archivo:T4 PolimorfismoyOS.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T4_PolimorfismoyOS.v&amp;diff=64"/>
		<updated>2018-08-04T15:36:24Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_4:_Polimorfismo_y_funciones_de_orden_superior_en_Coq&amp;diff=63</id>
		<title>Tema 4: Polimorfismo y funciones de orden superior en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_4:_Polimorfismo_y_funciones_de_orden_superior_en_Coq&amp;diff=63"/>
		<updated>2018-08-04T15:36:07Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se estudia el polimorfismo (abstrayendo el tipo de datos de las funciones) y orde superior (trabajando con las funciones como datos).&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T4_PolimorfismoyOS.v|T4_PolimorfismoyOS.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T4: Polimorfismo y funciones de orden superior en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T3_Listas.&lt;br /&gt;
&lt;br /&gt;
(* El contenido de la teoría es&lt;br /&gt;
   1. Polimorfismo&lt;br /&gt;
      1. Listas polimórficas  &lt;br /&gt;
         1. Inferencia de tipos&lt;br /&gt;
         2. Síntesis de los tipos de los argumentos  &lt;br /&gt;
         3. Argumentos implícitos  &lt;br /&gt;
         4. Explicitación de argumentos  &lt;br /&gt;
         5. Ejercicios  &lt;br /&gt;
      2. Polimorfismo de pares  &lt;br /&gt;
      3. Resultados opcionales polimórficos  &lt;br /&gt;
   2. Funciones como datos&lt;br /&gt;
      1. Funciones de orden superior &lt;br /&gt;
      2. Filtrado  &lt;br /&gt;
      3. Funciones anónimas  &lt;br /&gt;
      4. Aplicación a todos los elementos (map)&lt;br /&gt;
      5. Plegados (fold)  &lt;br /&gt;
      6. Funciones que construyen funciones  &lt;br /&gt;
   3. Ejercicios &lt;br /&gt;
   4. Bibliografía&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Polimorfismo&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Listas polimórficas  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Se suprime algunos avisos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Set Warnings &amp;quot;-notation-overridden,-parsing&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo (list X) para representar las listas&lt;br /&gt;
   de elementos de tipo X con los constructores nil y cons tales que &lt;br /&gt;
   + nil es la lista vacía y&lt;br /&gt;
   + (cons x ys) es la lista obtenida añadiendo el elemento x a la&lt;br /&gt;
     lista ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive list (X:Type) : Type :=&lt;br /&gt;
  | nil  : list X&lt;br /&gt;
  | cons : X -&amp;gt; list X -&amp;gt; list X.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Calcular el tipo de list.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check list.&lt;br /&gt;
(* ===&amp;gt; list : Type -&amp;gt; Type *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el tipo de (nil nat).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (nil nat).&lt;br /&gt;
(* ===&amp;gt; nil nat : list nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Calcular el tipo de (cons nat 3 (nil nat)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (cons nat 3 (nil nat)).&lt;br /&gt;
(* ===&amp;gt; cons nat 3 (nil nat) : list nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.5. Calcular el tipo de nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check nil.&lt;br /&gt;
(* ===&amp;gt; nil : forall X : Type, list X *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.6. Calcular el tipo de cons.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check cons.&lt;br /&gt;
(* ===&amp;gt; cons : forall X : Type, X -&amp;gt; list X -&amp;gt; list X *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.7. Calcular el tipo de &lt;br /&gt;
      (cons nat 2 (cons nat 1 (nil nat))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (cons nat 2 (cons nat 1 (nil nat))).&lt;br /&gt;
(* ==&amp;gt; cons nat 2 (cons nat 1 (nil nat)) : list nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.8. Definir la función&lt;br /&gt;
      repite (X : Type) (x : X) (n : nat) : list X&lt;br /&gt;
   tal que (repite X x n) es la lista, de elementos de tipo X, obtenida&lt;br /&gt;
   repitiendo n veces el elemento x. Por ejemplo,&lt;br /&gt;
      repite nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repite bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repite (X : Type) (x : X) (n : nat) : list X :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | 0    =&amp;gt; nil X&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; cons X x (repite X x n&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_repite1 :&lt;br /&gt;
  repite nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_repite2 :&lt;br /&gt;
  repite bool false 1 = cons bool false (nil bool).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ 1.1.1. Inferencia de tipos&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.9. Definir la función&lt;br /&gt;
      repite&amp;#039; X x n : list X&lt;br /&gt;
   tal que (repite&amp;#039; X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x. Por ejemplo,&lt;br /&gt;
      repite&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repite&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repite&amp;#039; X x n : list X :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | 0    =&amp;gt; nil X&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; cons X x (repite&amp;#039; X x n&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.10. Calcular los tipos de repite&amp;#039; y repite.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check repite&amp;#039;.&lt;br /&gt;
(* ===&amp;gt; forall X : Type, X -&amp;gt; nat -&amp;gt; list X *)&lt;br /&gt;
Check repite.&lt;br /&gt;
(* ===&amp;gt; forall X : Type, X -&amp;gt; nat -&amp;gt; list X *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ 1.1.2. Síntesis de los tipos de los argumentos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.11. Definir la función&lt;br /&gt;
      repite&amp;#039;&amp;#039; X x n : list X&lt;br /&gt;
   tal que (repite&amp;#039;&amp;#039; X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x, usando argumentos implícitos. Por ejemplo,&lt;br /&gt;
      repite&amp;#039;&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repite&amp;#039;&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repite&amp;#039;&amp;#039; X x n : list X :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | 0    =&amp;gt; nil _&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; cons _ x (repite&amp;#039;&amp;#039; _ x n&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.12. Definir la lista formada por los números naturales 1,&lt;br /&gt;
   2 y 3. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition list123 :=&lt;br /&gt;
  cons nat 1 (cons nat 2 (cons nat 3 (nil nat))).&lt;br /&gt;
&lt;br /&gt;
Definition list123&amp;#039; :=&lt;br /&gt;
  cons _ 1 (cons _ 2 (cons _ 3 (nil _))).&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ 1.1.3. Argumentos implícitos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.13. Especificar las siguientes funciones y sus argumentos&lt;br /&gt;
   explícitos e implícitos:&lt;br /&gt;
   + nil&lt;br /&gt;
   + constructor&lt;br /&gt;
   + repite&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Arguments nil {X}.&lt;br /&gt;
Arguments cons {X} _ _.&lt;br /&gt;
Arguments repite {X} x n.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.14. Definir la lista formada por los números naturales 1,&lt;br /&gt;
   2 y 3. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition list123&amp;#039;&amp;#039; := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.15. Definir la función&lt;br /&gt;
      repite&amp;#039;&amp;#039;&amp;#039; {X : Type} (x : X) (n : nat) : list X&lt;br /&gt;
   tal que (repite&amp;#039;&amp;#039; X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x, usando argumentos implícitos. Por ejemplo,&lt;br /&gt;
      repite&amp;#039;&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repite&amp;#039;&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repite&amp;#039;&amp;#039;&amp;#039; {X : Type} (x : X) (n : nat) : list X :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | 0    =&amp;gt; nil&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; cons x (repite&amp;#039;&amp;#039;&amp;#039; x n&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_repite&amp;#039;&amp;#039;&amp;#039;1 :&lt;br /&gt;
  repite&amp;#039;&amp;#039;&amp;#039; 4 2 = cons 4 (cons 4 nil).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_repite&amp;#039;&amp;#039;&amp;#039;2 :&lt;br /&gt;
  repite false 1 = cons false nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.16. Definir el tipo (list&amp;#039; {X}) para representar las&lt;br /&gt;
   listas de elementos de tipo X con los constructores nil&amp;#039; y cons&amp;#039;&lt;br /&gt;
   tales que  &lt;br /&gt;
   + nil&amp;#039; es la lista vacía y&lt;br /&gt;
   + (cons&amp;#039; x ys) es la lista obtenida añadiendo el elemento x a la&lt;br /&gt;
     lista ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive list&amp;#039; {X:Type} : Type :=&lt;br /&gt;
  | nil&amp;#039;  : list&amp;#039;&lt;br /&gt;
  | cons&amp;#039; : X -&amp;gt; list&amp;#039; -&amp;gt; list&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.17. Definir la función&lt;br /&gt;
      conc {X : Type} (xs ys : list X) : (list X)&lt;br /&gt;
   tal que (conc xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint conc {X : Type} (xs ys : list X) : (list X) :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil        =&amp;gt; ys&lt;br /&gt;
  | cons x xs&amp;#039; =&amp;gt; cons x (conc xs&amp;#039; ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.18. Definir la función&lt;br /&gt;
      inversa {X:Type} (l:list X) : list X&lt;br /&gt;
   tal que (inversa xs) es la inversa de xs. Por ejemplo,&lt;br /&gt;
      inversa (cons 1 (cons 2 nil)) = (cons 2 (cons 1 nil)).&lt;br /&gt;
      inversa (cons true nil)       = cons true nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint inversa {X:Type} (xs:list X) : list X :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil        =&amp;gt; nil&lt;br /&gt;
  | cons x xs&amp;#039; =&amp;gt; conc (inversa xs&amp;#039;) (cons x nil)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_inversa1 :&lt;br /&gt;
  inversa (cons 1 (cons 2 nil)) = (cons 2 (cons 1 nil)).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_inversa2:&lt;br /&gt;
  inversa (cons true nil) = cons true nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.19. Definir la función&lt;br /&gt;
      longitud {X : Type} (xs : list X) : nat &lt;br /&gt;
   tal que (longitud xs) es el número de elementos de xs. Por ejemplo,&lt;br /&gt;
      longitud (cons 1 (cons 2 (cons 3 nil))) = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint longitud {X : Type} (xs : list X) : nat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil        =&amp;gt; 0&lt;br /&gt;
  | cons _ xs&amp;#039; =&amp;gt; S (longitud xs&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_longitud1:&lt;br /&gt;
  longitud (cons 1 (cons 2 (cons 3 nil))) = 3.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ 1.1.4. Explicitación de argumentos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.20. Evaluar la siguiente expresión&lt;br /&gt;
      Fail Definition n_nil := nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fail Definition n_nil := nil.&lt;br /&gt;
(* ==&amp;gt; Error: Cannot infer the implicit parameter X of nil. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.21. Completar la definición anterior para obtener la&lt;br /&gt;
   lista vacía de números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª solución *)&lt;br /&gt;
Definition n_nil : list nat := nil.&lt;br /&gt;
&lt;br /&gt;
(* 2ª solución *)&lt;br /&gt;
Definition n_nil&amp;#039; := @nil nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.22. Definir las siguientes abreviaturas&lt;br /&gt;
   + &amp;quot;x :: y&amp;quot;         para (cons x y)&lt;br /&gt;
   + &amp;quot;[ ]&amp;quot;            para nil&lt;br /&gt;
   + &amp;quot;[ x ; .. ; y ]&amp;quot; para (cons x .. (cons y []) ..).&lt;br /&gt;
   + &amp;quot;x ++ y&amp;quot;         para (conc x y)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: y&amp;quot;         := (cons x y)&lt;br /&gt;
                             (at level 60, right associativity).&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot;            := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y []) ..).&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot;         := (conc x y)&lt;br /&gt;
                              (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.23. Definir la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition list123&amp;#039;&amp;#039;&amp;#039; := [1; 2; 3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ 1.1.5. Ejercicios  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1.1. Demostrar que la lista vacía es el elemento neutro&lt;br /&gt;
   por la derecha de la concatenación.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_nil: forall (X:Type), forall xs:list X,&lt;br /&gt;
  xs ++ [] = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  [ ] ++ [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : xs&amp;#039; ++ [ ] = xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (x :: xs&amp;#039;) ++ [ ] = x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                     (* x :: (xs&amp;#039; ++ [ ]) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                (* x :: xs&amp;#039; = x :: xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1.2. Demostrar que la concatenación es asociativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_asociativa : forall A (xs ys zs:list A),&lt;br /&gt;
  xs ++ (ys ++ zs) = (xs ++ ys) ++ zs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros A xs ys zs.           (* A : Type&lt;br /&gt;
                                  xs, ys, zs : list A&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  xs ++ (ys ++ zs) = (xs ++ ys) ++ zs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  +                            (* A : Type&lt;br /&gt;
                                  ys, zs : list A&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  [ ] ++ (ys ++ zs) = ([ ] ++ ys) ++ zs *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                            (* A : Type&lt;br /&gt;
                                  x : A&lt;br /&gt;
                                  xs&amp;#039;, ys, zs : list A&lt;br /&gt;
                                  HI : xs&amp;#039; ++ (ys ++ zs) = (xs&amp;#039; ++ ys) ++ zs&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (x :: xs&amp;#039;) ++ (ys ++ zs) = &lt;br /&gt;
                                  ((x :: xs&amp;#039;) ++ ys) ++ zs *)&lt;br /&gt;
    simpl.                     (* x :: (xs&amp;#039; ++ (ys ++ zs)) = &lt;br /&gt;
                                  x :: ((xs&amp;#039; ++ ys) ++ zs) *)&lt;br /&gt;
    rewrite HI.                (* x :: ((xs&amp;#039; ++ ys) ++ zs) = &lt;br /&gt;
                                  x :: ((xs&amp;#039; ++ ys) ++ zs) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1.3. Demostrar que la longitud de una concatenación es la&lt;br /&gt;
   suma de las longitudes de las listas (es decir, es un homomorfismo).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma conc_longitud: forall (X:Type) (xs ys : list X),&lt;br /&gt;
  longitud (xs ++ ys) = longitud xs + longitud ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs ys.              (* X : Type&lt;br /&gt;
                                  xs, ys : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (xs ++ ys) = &lt;br /&gt;
                                  longitud xs + longitud ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  ys : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud ([ ] ++ ys) = &lt;br /&gt;
                                  longitud [ ] + longitud ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039;, ys : list X&lt;br /&gt;
                                  HI : longitud (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       longitud xs&amp;#039; + longitud ys&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) + longitud ys *)&lt;br /&gt;
    simpl.                     (* S (longitud (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                  S (longitud xs&amp;#039; + longitud ys) *)&lt;br /&gt;
    rewrite HI.                (* S (longitud xs&amp;#039; + longitud ys) = &lt;br /&gt;
                                  S (longitud xs&amp;#039; + longitud ys) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1.4. Demostrar que&lt;br /&gt;
      inversa (xs ++ ys) = inversa ys ++ inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_conc: forall X (xs ys : list X),&lt;br /&gt;
  inversa (xs ++ ys) = inversa ys ++ inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs ys.              (* X : Type&lt;br /&gt;
                                  xs, ys : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (xs ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  ys : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa ([ ] ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa [ ] *)&lt;br /&gt;
    simpl.&lt;br /&gt;
    rewrite conc_nil.&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039;, ys : list X&lt;br /&gt;
                                  HI : inversa (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       inversa ys ++ inversa xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* inversa (xs&amp;#039; ++ ys) ++ [x] = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    rewrite HI.                (* (inversa ys ++ inversa xs&amp;#039;) ++ [x] = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    rewrite conc_asociativa.   (* (inversa ys ++ inversa xs&amp;#039;) ++ [x] = &lt;br /&gt;
                                  (inversa ys ++ inversa xs&amp;#039;) ++ [x] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1.5. Demostrar que la inversa es involutiva; es decir,&lt;br /&gt;
      inversa (inversa xs) = xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_involutiva : forall X : Type, forall xs : list X,&lt;br /&gt;
  inversa (inversa xs) = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                 (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa xs) = xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa [ ]) = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : inversa (inversa xs&amp;#039;) = xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa (x :: xs&amp;#039;)) = x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                     (* inversa (inversa xs&amp;#039; ++ [x]) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite inversa_conc.      (* inversa [x] ++ inversa (inversa xs&amp;#039;) = &lt;br /&gt;
                                  x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                (* inversa [x] ++ xs&amp;#039; = x :: xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Polimorfismo de pares  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo prod (X Y) con el constructor par tal&lt;br /&gt;
   que (par x y) es el par cuyas componentes son x e y.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive prod (X Y : Type) : Type :=&lt;br /&gt;
  | par : X -&amp;gt; Y -&amp;gt; prod X Y.&lt;br /&gt;
&lt;br /&gt;
Arguments par {X} {Y} _ _.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la abreviaturas&lt;br /&gt;
      &amp;quot;( x , y )&amp;quot; para (par x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (par x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la abreviatura&lt;br /&gt;
      &amp;quot;X * Y&amp;quot; para (prod X Y) &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;X * Y&amp;quot; := (prod X Y) : type_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      fst {X Y : Type} (p : X * Y) : X&lt;br /&gt;
   tal que (fst p) es la primera componente del par p. Por ejemplo,&lt;br /&gt;
      fst (par 3 5) = 3&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst {X Y : Type} (p : X * Y) : X :=&lt;br /&gt;
  match p with&lt;br /&gt;
  | (x, y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (fst (par 3 5)).&lt;br /&gt;
(* = 3 : nat*)&lt;br /&gt;
&lt;br /&gt;
Example prop_fst: fst (par 3 5) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.5. Definir la función&lt;br /&gt;
      snd {X Y : Type} (p : X * Y) &lt;br /&gt;
   tal que (snd p) es la segunda componente del par p. Por ejemplo,&lt;br /&gt;
      snd (par 3 5) = 5 &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd {X Y : Type} (p : X * Y) : Y :=&lt;br /&gt;
  match p with&lt;br /&gt;
  | (x, y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (snd (par 3 5)).&lt;br /&gt;
(* = 5 : nat*)&lt;br /&gt;
&lt;br /&gt;
Example prop_snd: snd (par 3 5) = 5.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Definir la función&lt;br /&gt;
      empareja {X Y : Type} (xs : list X) (ys : list Y) : list (X*Y) &lt;br /&gt;
   tal que (empareja xs ys) es la lista obtenida emparejando los&lt;br /&gt;
   elementos de xs y ys. Por ejemplo,&lt;br /&gt;
      empareja [2;6] [3;5;7]     = [(2, 3); (6, 5)].&lt;br /&gt;
      empareja [2;6;4;8] [3;5;7] = [(2, 3); (6, 5); (4, 7)].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint empareja {X Y : Type} (xs : list X) (ys : list Y) : list (X*Y) :=&lt;br /&gt;
  match xs, ys with&lt;br /&gt;
  | []     , _       =&amp;gt; []&lt;br /&gt;
  | _      , []      =&amp;gt; []&lt;br /&gt;
  | x :: tx, y :: ty =&amp;gt; (x, y) :: (empareja tx ty)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (empareja [2;6] [3;5;7]).&lt;br /&gt;
(* = [(2, 3); (6, 5)] : list (nat * nat)*)&lt;br /&gt;
Compute (empareja [2;6;4;8] [3;5;7]).&lt;br /&gt;
(* = [(2, 3); (6, 5); (4, 7)] : list (nat * nat)*)&lt;br /&gt;
&lt;br /&gt;
Example prop_combina1: empareja [2;6] [3;5;7] = [(2, 3); (6, 5)].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_combina2: empareja [2;6;4;8] [3;5;7] = [(2,3);(6, 5);(4,7)].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Evaluar la expresión&lt;br /&gt;
      Check @empareja&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check @empareja.&lt;br /&gt;
(* ==&amp;gt; forall X Y : Type, list X -&amp;gt; list Y -&amp;gt; list (X * Y)*)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Definir la función&lt;br /&gt;
      desempareja {X Y : Type} (ps : list (X*Y)) : (list X) * (list Y)&lt;br /&gt;
   tal que (desempareja ps) es el par de lista (xs,ys) cuyo&lt;br /&gt;
   emparejamiento es l. Por ejemplo,&lt;br /&gt;
      desempareja [(1,false);(2,false)] = ([1;2],[false;false]).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint desempareja {X Y:Type} (ps:list (X*Y)) : (list X) * (list Y) :=&lt;br /&gt;
  match ps with&lt;br /&gt;
  | []            =&amp;gt; ([], [])&lt;br /&gt;
  | (x, y) :: ps&amp;#039; =&amp;gt; let ps&amp;#039;&amp;#039; := desempareja ps&amp;#039;&lt;br /&gt;
                    in (x :: fst ps&amp;#039;&amp;#039;, y :: snd ps&amp;#039;&amp;#039;)&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Compute (desempareja [(2, 3); (6, 5)]).&lt;br /&gt;
(* = ([2; 6], [3; 5]) : list nat * list nat*)&lt;br /&gt;
&lt;br /&gt;
Example prop_desempareja:&lt;br /&gt;
  desempareja [(2, 3); (6, 5)] = ([2; 6], [3; 5]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Resultados opcionales polimórficos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Definir el tipo (Opcional X) con los constructores Some&lt;br /&gt;
   y None tales que &lt;br /&gt;
   + (Some x) es un valor de tipo X.&lt;br /&gt;
   + None es el valor nulo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive Opcional (X:Type) : Type :=&lt;br /&gt;
  | Some : X -&amp;gt; Opcional X&lt;br /&gt;
  | None : Opcional X.&lt;br /&gt;
&lt;br /&gt;
Arguments Some {X} _.&lt;br /&gt;
Arguments None {X}.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.3.1. Definir la función&lt;br /&gt;
      nthOpcional {X : Type} (xs : list X) (n : nat) : Opcional X :=&lt;br /&gt;
   tal que (nthOpcional xs n) es el n-ésimo elemento de xs o None&lt;br /&gt;
   si la lista tiene menos de n elementos. Por ejemplo, &lt;br /&gt;
      nthOpcional [4;5;6;7] 0 = Some 4.&lt;br /&gt;
      nthOpcional [[1];[2]] 1 = Some [2].&lt;br /&gt;
      nthOpcional [true] 2    = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nthOpcional {X : Type} (xs : list X) (n : nat) : Opcional X :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []       =&amp;gt; None&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; if iguales_nat n O&lt;br /&gt;
               then Some x&lt;br /&gt;
               else nthOpcional xs&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional1 : nthOpcional [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional2 : nthOpcional [[1];[2]] 1 = Some [2].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional3 : nthOpcional [true] 2 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.3.2. Definir la función&lt;br /&gt;
      primeroOpcional {X : Type} (xs : list X) : Opcional X&lt;br /&gt;
   tal que (primeroOpcional xs) es el primer elemento de xs, si xs es no&lt;br /&gt;
   vacía; o es None, en caso contrario. Por ejemplo,&lt;br /&gt;
      primeroOpcional [1;2]     = Some 1.&lt;br /&gt;
      primeroOpcional [[1];[2]] = Some [1].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition primeroOpcional {X : Type} (xs : list X) : Opcional X :=&lt;br /&gt;
 match xs with &lt;br /&gt;
    | []     =&amp;gt; None&lt;br /&gt;
    | x :: _ =&amp;gt; Some x&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Check @primeroOpcional.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional1 : primeroOpcional [1;2] = Some 1.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional2 : primeroOpcional  [[1];[2]]  = Some [1].&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Funciones como datos&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.1. Funciones de orden superior &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Definir la función &lt;br /&gt;
      aplica3veces {X : Type} (f : X -&amp;gt; X) (n : X) : X &lt;br /&gt;
   tal que (aplica3veces f) aplica 3 veces la función f. Por ejemplo,&lt;br /&gt;
      aplica3veces menosDos 9     = 3.&lt;br /&gt;
      aplica3veces negacion true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition aplica3veces {X : Type} (f : X -&amp;gt; X) (n : X) : X :=&lt;br /&gt;
  f (f (f n)).&lt;br /&gt;
&lt;br /&gt;
Check @aplica3veces.&lt;br /&gt;
(* ===&amp;gt; aplica3veces : forall X : Type, (X -&amp;gt; X) -&amp;gt; X -&amp;gt; X *)&lt;br /&gt;
&lt;br /&gt;
Example prop_aplica3veces: aplica3veces menosDos 9 = 3.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_aplica3veces&amp;#039;: aplica3veces negacion true = false.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.2. Filtrado  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Definir la función&lt;br /&gt;
      filtra {X : Type} (p : X -&amp;gt; bool) (xs : list X) : (list X)&lt;br /&gt;
   tal que (filtra p xs) es la lista de los elementos de xs que&lt;br /&gt;
   verifican p. Por ejemplo,&lt;br /&gt;
      filtra esPar [1;2;3;4] = [2;4].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint filtra {X : Type} (p : X -&amp;gt; bool) (xs : list X) : (list X) :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []       =&amp;gt; []&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; if p x&lt;br /&gt;
               then x :: (filtra p xs&amp;#039;)&lt;br /&gt;
               else filtra p xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_filtra1: filtra esPar [1;2;3;4] = [2;4].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Definir la función&lt;br /&gt;
      unitarias {X : Type} (xss : list (list X)) : list (list X) :=&lt;br /&gt;
   tal que (unitarias xss) es la lista de listas unitarias de xss. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      unitarias [[1;2];[3];[4];[5;6;7];[];[8]] = [[3];[4];[8]]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esUnitaria {X : Type} (xs : list X) : bool :=&lt;br /&gt;
  iguales_nat (longitud xs) 1.&lt;br /&gt;
&lt;br /&gt;
Definition unitarias {X : Type} (xss : list (list X)) : list (list X) :=&lt;br /&gt;
  filtra esUnitaria xss.&lt;br /&gt;
  &lt;br /&gt;
Compute (unitarias [[1; 2]; [3]; [4]; [5;6;7]; []; [8]]).&lt;br /&gt;
(* = [[3]; [4]; [8]] : list (list nat)*)&lt;br /&gt;
&lt;br /&gt;
Example prop_unitarias:&lt;br /&gt;
  unitarias [[1; 2]; [3]; [4]; [5;6;7]; []; [8]]&lt;br /&gt;
  = [[3]; [4]; [8]].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Definir la función&lt;br /&gt;
      nImpares (xs : list nat) : nat &lt;br /&gt;
   tal que nImpares xs) es el número de elementos impares de xs. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      nImpares [1;0;3;1;4;5] = 4.&lt;br /&gt;
      nImpares [0;2;4]       = 0.&lt;br /&gt;
      nImpares nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nImpares (xs : list nat) : nat :=&lt;br /&gt;
  longitud (filtra esImpar xs).&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares1:   nImpares [1;0;3;1;4;5] = 4.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares2:   nImpares [0;2;4] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares3:   nImpares nil = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.3. Funciones anónimas  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que&lt;br /&gt;
      aplica3veces (fun n =&amp;gt; n * n) 2 = 256.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example prop_anon_fun&amp;#039;:&lt;br /&gt;
  aplica3veces (fun n =&amp;gt; n * n) 2 = 256.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Calcular&lt;br /&gt;
      filtra (fun xs =&amp;gt; iguales_nat (longitud xs) 1)&lt;br /&gt;
             [ [1; 2]; [3]; [4]; [5;6;7]; []; [8] ]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (filtra (fun xs =&amp;gt; iguales_nat (longitud xs) 1)&lt;br /&gt;
                [ [1; 2]; [3]; [4]; [5;6;7]; []; [8] ]).&lt;br /&gt;
(* = [[3]; [4]; [8]] : list (list nat)*)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.3. Definir la función&lt;br /&gt;
      filtra_pares_menores7 (xs : list nat) : list nat&lt;br /&gt;
   tal que (filtra_pares_mayores7 xs) es la lista de los elementos de xs&lt;br /&gt;
   que son pares y mayores que 7. Por ejemplo,&lt;br /&gt;
      filtra_pares_mayores7 [1;2;6;9;10;3;12;8] = [10;12;8].&lt;br /&gt;
      filtra_pares_mayores7 [5;2;6;19;129]      = [].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition filtra_pares_mayores7 (xs : list nat) : list nat :=&lt;br /&gt;
  filtra (fun x =&amp;gt; esPar x &amp;amp;&amp;amp; menor_o_igual 7 x) xs.&lt;br /&gt;
&lt;br /&gt;
Example prop_filtra_pares_mayores7_1 :&lt;br /&gt;
  filtra_pares_mayores7 [1;2;6;9;10;3;12;8] = [10;12;8].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_filtra_pares_mayores7_2 :&lt;br /&gt;
  filtra_pares_mayores7 [5;2;6;19;129] = [].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.3.4. Definir la función&lt;br /&gt;
      partition {X : Type} (p : X -&amp;gt; bool) (xs : list X) : list X * list X&lt;br /&gt;
   tal que (patition p xs) es el par de listas (ys,zs) donde xs es la&lt;br /&gt;
   lista de los elementos de xs que cumplen p y zs la de las que no lo&lt;br /&gt;
   cumplen. Por ejemplo,&lt;br /&gt;
      partition esImpar [1;2;3;4;5]         = ([1;3;5], [2;4]).&lt;br /&gt;
      partition (fun x =&amp;gt; false) [5;9;0] = ([], [5;9;0]).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition partition {X : Type}&lt;br /&gt;
                     (p : X -&amp;gt; bool)&lt;br /&gt;
                     (xs : list X)&lt;br /&gt;
                   : list X * list X :=&lt;br /&gt;
  (filtra p xs, filtra (fun x =&amp;gt; negacion (p x)) xs).&lt;br /&gt;
&lt;br /&gt;
Example prop_partition1: partition esImpar [1;2;3;4;5] = ([1;3;5], [2;4]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_partition2: partition (fun x =&amp;gt; false) [5;9;0] = ([], [5;9;0]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.4. Aplicación a todos los elementos (map)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.4.1. Definir la función&lt;br /&gt;
      map {X Y:Type} (f : X -&amp;gt; Y) (xs:list X) : list Y &lt;br /&gt;
   tal que (map f xs) es la lista obtenida aplicando f a todos los&lt;br /&gt;
   elementos de xs. Por ejemplo,&lt;br /&gt;
      map (fun x =&amp;gt; plus 3 x) [2;0;2] = [5;3;5].&lt;br /&gt;
      map esImpar [2;1;2;5] = [false;true;false;true].&lt;br /&gt;
      map (fun n =&amp;gt; [evenb n;esImpar n]) [2;1;2;5]&lt;br /&gt;
        = [[true;false];[false;true];[true;false];[false;true]].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint map {X Y:Type} (f : X -&amp;gt; Y) (xs : list X) : list Y :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | []       =&amp;gt; []&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; f x :: map f xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_map1:&lt;br /&gt;
  map (fun x =&amp;gt; plus 3 x) [2;0;2] = [5;3;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_map2:&lt;br /&gt;
  map esImpar [2;1;2;5] = [false;true;false;true].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_map3:&lt;br /&gt;
    map (fun n =&amp;gt; [esPar n ; esImpar n]) [2;1;2;5]&lt;br /&gt;
  = [[true;false];[false;true];[true;false];[false;true]].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.4.2. Demostrar que&lt;br /&gt;
      map f (inversa l) = inversa (map f l).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma map_conc: forall (X Y : Type) (f : X -&amp;gt; Y) (xs ys : list X),&lt;br /&gt;
    map f (xs ++ ys) = map f xs ++ map f ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y f xs ys.          (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  xs, ys : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  map f (xs ++ ys) = map f xs ++ map f ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  ys : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  map f ([ ] ++ ys) = map f [ ] ++ map f ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039;, ys : list X&lt;br /&gt;
                                  HI : map f (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       map f xs&amp;#039; ++ map f ys&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  map f ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  map f (x :: xs&amp;#039;) ++ map f ys *)&lt;br /&gt;
    simpl.                     (* f x :: map f (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                  f x :: (map f xs&amp;#039; ++ map f ys) *)&lt;br /&gt;
    rewrite HI.                (* f x :: (map f xs&amp;#039; ++ map f ys) = &lt;br /&gt;
                                  f x :: (map f xs&amp;#039; ++ map f ys) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem map_inversa : forall (X Y : Type) (f : X -&amp;gt; Y) (xs : list X),&lt;br /&gt;
  map f (inversa xs) = inversa (map f xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y f xs.             (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  map f (inversa xs) = inversa (map f xs) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  map f (inversa [ ]) = inversa (map f [ ]) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                            (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : map f (inversa xs&amp;#039;) = inversa (map f xs&amp;#039;)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  map f (inversa (x :: xs&amp;#039;)) = &lt;br /&gt;
                                  inversa (map f (x :: xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                     (* map f (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                  inversa (map f xs&amp;#039;) ++ [f x] *)&lt;br /&gt;
    rewrite map_conc.          (* map f (inversa xs&amp;#039;) ++ map f [x] = &lt;br /&gt;
                                  inversa (map f xs&amp;#039;) ++ [f x] *)&lt;br /&gt;
    rewrite HI.                (* inversa (map f xs&amp;#039;) ++ map f [x] = &lt;br /&gt;
                                  inversa (map f xs&amp;#039;) ++ [f x] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.4.3. Definir la función&lt;br /&gt;
      conc_map {X Y : Type} (f : X -&amp;gt; list Y) (xs :list X) : (list Y)&lt;br /&gt;
   tal que (conc_map f xs) es la concatenación de las listas obtenidas&lt;br /&gt;
   aplicando f a l. Por ejemplo,&lt;br /&gt;
      conc_map (fun n =&amp;gt; [n;n;n]) [1;5;4] = [1; 1; 1; 5; 5; 5; 4; 4; 4].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint conc_map {X Y : Type} (f : X -&amp;gt; list Y) (xs : list X) : (list Y) :=&lt;br /&gt;
   match xs with&lt;br /&gt;
  | []       =&amp;gt; []&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; f x ++ conc_map f xs&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_conc_map:&lt;br /&gt;
  conc_map (fun n =&amp;gt; [n;n;n]) [1;5;4]&lt;br /&gt;
  = [1; 1; 1; 5; 5; 5; 4; 4; 4].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.4.4. Definir la función&lt;br /&gt;
      map_opcional {X Y : Type} (f : X -&amp;gt; Y) (o : Opcional X) : Opcional Y&lt;br /&gt;
   tal que (map_opcional f o) es la aplicación de f a o. Por ejemplo,&lt;br /&gt;
      map_opcional S (Some 3) = Some 4&lt;br /&gt;
      map_opcional S None     = None&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition map_opcional {X Y : Type} (f : X -&amp;gt; Y) (o : Opcional X)&lt;br /&gt;
                        : Opcional Y :=&lt;br /&gt;
  match o with&lt;br /&gt;
    | None   =&amp;gt; None&lt;br /&gt;
    | Some x =&amp;gt; Some (f x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (map_opcional S (Some 3)).&lt;br /&gt;
(* = Some 4 : Opcional nat*)&lt;br /&gt;
Compute (map_opcional S None).&lt;br /&gt;
(* = None : Opcional nat*)&lt;br /&gt;
&lt;br /&gt;
Example prop_map_opcional1: map_opcional S (Some 3) = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_map_opcional2: map_opcional S None = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.5. Plegados (fold)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.1. Definir la función&lt;br /&gt;
      fold {X Y:Type} (f: X -&amp;gt; Y- &amp;gt; Y) (xs : list X) (b : Y) : Y&lt;br /&gt;
   tal que (fold f xs b) es el plegado de xs con la operación f a partir&lt;br /&gt;
   del elemento b. Por ejemplo,&lt;br /&gt;
      fold mult [1;2;3;4] 1                       = 24.&lt;br /&gt;
      fold conjuncion [true;true;false;true] true = false.&lt;br /&gt;
      fold conc  [[1];[];[2;3];[4]] []            = [1;2;3;4].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint fold {X Y:Type} (f: X -&amp;gt; Y -&amp;gt; Y) (xs : list X) (b : Y) : Y :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; b&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; f x (fold f xs&amp;#039; b)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Check (fold conjuncion).&lt;br /&gt;
(* ===&amp;gt; fold conjuncion : list bool -&amp;gt; bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
Example fold_example1:&lt;br /&gt;
  fold mult [1;2;3;4] 1 = 24.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example fold_example2 :&lt;br /&gt;
  fold conjuncion [true;true;false;true] true = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example fold_example3 :&lt;br /&gt;
  fold conc  [[1];[];[2;3];[4]] [] = [1;2;3;4].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.6. Funciones que construyen funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.1. Definir la función&lt;br /&gt;
      constante {X : Type} (x : X) : nat -&amp;gt; X&lt;br /&gt;
   tal que (constante x) es la función que a todos los naturales le&lt;br /&gt;
   asigna el x. Por ejemplo, &lt;br /&gt;
      (constante 5) 99 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition constante {X : Type} (x : X) : nat -&amp;gt; X :=&lt;br /&gt;
  fun (k : nat) =&amp;gt; x.&lt;br /&gt;
&lt;br /&gt;
Example prop_constante: (constante 5) 99 = 5.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.2. Calcular el tipo de plus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check plus.&lt;br /&gt;
(* ==&amp;gt; nat -&amp;gt; nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.6.3. Definir la función&lt;br /&gt;
      plus3 : nat -&amp;gt; nat&lt;br /&gt;
   tal que (plus3 x) es tres más x. Por ejemplo,&lt;br /&gt;
      plus3 4                 = 7.&lt;br /&gt;
      aplica3veces plus3 0    = 9.&lt;br /&gt;
      aplica3veces (plus 3) 0 = 9.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition plus3 := plus 3.&lt;br /&gt;
&lt;br /&gt;
Example prop_plus3a: plus3 4 = 7.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_plus3b: aplica3veces plus3 0 = 9.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_plus3c: aplica3veces (plus 3) 0 = 9.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module Exercises.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Definir, usando fold, la función&lt;br /&gt;
      longitudF {X : Type} (xs : list X) : nat&lt;br /&gt;
   tal que (longitudF xs) es la longitud de xs. Por ejemplo,&lt;br /&gt;
      longitudF [4;7;0] = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Definition longitudF {X : Type} (xs : list X) : nat :=&lt;br /&gt;
  fold (fun _ n =&amp;gt; S n) xs 0.&lt;br /&gt;
&lt;br /&gt;
Example prop_longitudF1: longitudF [4;7;0] = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2. Demostrar que&lt;br /&gt;
      longitudF l = longitud l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem longitudF_longitud: forall X (xs : list X),&lt;br /&gt;
  longitudF xs = longitud xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X xs.                 (* X : Type&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitudF xs = longitud xs *)&lt;br /&gt;
  unfold longitudF.            (* fold (fun (_ : X) (n : nat) =&amp;gt; S n) xs 0 = &lt;br /&gt;
                                  longitud xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  fold (fun (_ : X) (n : nat) =&amp;gt; S n) [ ] 0 = &lt;br /&gt;
                                  longitud [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : fold (fun (_:X) (n:nat) =&amp;gt; S n) xs&amp;#039; 0 =&lt;br /&gt;
                                       longitud xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  fold (fun (_:X) (n:nat) =&amp;gt; S n) (x::xs&amp;#039;) 0 = &lt;br /&gt;
                                  longitud (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* S (fold (fun (_:X) (n:nat) =&amp;gt; S n) xs&amp;#039; 0) = &lt;br /&gt;
                                  S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite HI.                (* S (longitud xs&amp;#039;) = S (longitud xs&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Definir, usando fold, la función&lt;br /&gt;
      mapF {X Y : Type} (f : X -&amp;gt; Y) (xs : list X) : list Y&lt;br /&gt;
   tal que (mapF f xs) es la lista obtenida aplicando f a los&lt;br /&gt;
   elementos de l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mapF {X Y : Type} (f : X -&amp;gt; Y) (xs : list X) : list Y :=&lt;br /&gt;
   fold (fun x t =&amp;gt; (f x) :: t)  xs [].&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4. Demostrar que mapF es equivalente a map.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem mapF_correct : forall (X Y : Type) (f : X -&amp;gt; Y) (xs : list X),&lt;br /&gt;
    mapF f xs = map f xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X Y f xs.             (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  xs : list X&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  mapF f xs = map f xs *)&lt;br /&gt;
  unfold mapF.                 (* fold (fun (x:X) (t:list Y) =&amp;gt; f x::t) xs [] &lt;br /&gt;
                                  = map f xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  fold (fun (x:X) (t:list Y) =&amp;gt; f x :: t) [] []&lt;br /&gt;
                                  = map f [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* X : Type&lt;br /&gt;
                                  Y : Type&lt;br /&gt;
                                  f : X -&amp;gt; Y&lt;br /&gt;
                                  x : X&lt;br /&gt;
                                  xs&amp;#039; : list X&lt;br /&gt;
                                  HI : fold (fun (x:X) (t:list Y) =&amp;gt; f x :: t) &lt;br /&gt;
                                            xs&amp;#039; [ ] &lt;br /&gt;
                                       = map f xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  fold (fun (x0:X) (t:list Y) =&amp;gt; f x0 :: t) &lt;br /&gt;
                                       (x :: xs&amp;#039;) [ ] &lt;br /&gt;
                                  = map f (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* f x :: fold (fun (x0:X) (t:list Y) =&amp;gt; &lt;br /&gt;
                                               f x0 :: t) xs&amp;#039; [ ] &lt;br /&gt;
                                  = f x :: map f xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                (* f x :: map f xs&amp;#039; = f x :: map f xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.5. Definir la función&lt;br /&gt;
      curry {X Y Z : Type} (f : X * Y -&amp;gt; Z) (x : X) (y : Y) : Z&lt;br /&gt;
   tal que (curry f x y) es la versión curryficada de f. Por ejemplo,&lt;br /&gt;
      curry fst 3 5 = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition curry {X Y Z : Type}&lt;br /&gt;
  (f : X * Y -&amp;gt; Z) (x : X) (y : Y) : Z := f (x, y).&lt;br /&gt;
&lt;br /&gt;
Compute (curry fst 3 5).&lt;br /&gt;
(* = 3 : nat*)&lt;br /&gt;
&lt;br /&gt;
Example prop_curry: curry fst 3 5 = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.6. Definir la función&lt;br /&gt;
      uncurry {X Y Z : Type} (f : X -&amp;gt; Y -&amp;gt; Z) (p : X * Y) : Z&lt;br /&gt;
   tal que (uncurry f p) es la versión incurryficada de f.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition uncurry {X Y Z : Type}&lt;br /&gt;
  (f : X -&amp;gt; Y -&amp;gt; Z) (p : X * Y) : Z := f (fst p) (snd p).&lt;br /&gt;
&lt;br /&gt;
Compute (uncurry mult (2,5)).&lt;br /&gt;
(* = 10 : nat*)&lt;br /&gt;
&lt;br /&gt;
Example prop_uncurry: uncurry mult (2,5) = 10.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.7. Calcular el tipo de las funcciones curry y uncurry.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check @curry.&lt;br /&gt;
(* ===&amp;gt; forall X Y Z : Type, (X * Y -&amp;gt; Z) -&amp;gt; X -&amp;gt; Y -&amp;gt; Z *)&lt;br /&gt;
&lt;br /&gt;
Check @uncurry.&lt;br /&gt;
(* forall X Y Z : Type, (X -&amp;gt; Y -&amp;gt; Z) -&amp;gt; X * Y -&amp;gt; Z *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.8. Demostrar que&lt;br /&gt;
      curry (uncurry f) x y = f x y&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem uncurry_curry : forall (X Y Z : Type)&lt;br /&gt;
                          (f : X -&amp;gt; Y -&amp;gt; Z)&lt;br /&gt;
                          x y,&lt;br /&gt;
  curry (uncurry f) x y = f x y.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.9. Demostrar que&lt;br /&gt;
      uncurry (curry f) p = f p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem curry_uncurry : forall (X Y Z : Type)&lt;br /&gt;
                          (f : (X * Y) -&amp;gt; Z)&lt;br /&gt;
                          (p : X * Y),&lt;br /&gt;
  uncurry (curry f) p = f p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros.      (* X : Type&lt;br /&gt;
                  Y : Type&lt;br /&gt;
                  Z : Type&lt;br /&gt;
                  f : X * Y -&amp;gt; Z&lt;br /&gt;
                  p : X * Y&lt;br /&gt;
                  ============================&lt;br /&gt;
                  uncurry (curry f) p = f p *)&lt;br /&gt;
  destruct p.  (* uncurry (curry f) (x, y) = f (x, y) *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Module Church.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.1. En los siguientes ejercicios se trabajará con la&lt;br /&gt;
   definición de Church de los números naturales: el número natural n es&lt;br /&gt;
   la función que toma como argumento una función f y devuelve como&lt;br /&gt;
   valor la aplicación de n veces la función f. &lt;br /&gt;
&lt;br /&gt;
   Definir el tipo nat para los números naturales de Church. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Definition nat := forall X : Type, (X -&amp;gt; X) -&amp;gt; X -&amp;gt; X.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.2. Definir la función&lt;br /&gt;
      uno : nat&lt;br /&gt;
   tal que uno es el número uno de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition uno : nat :=&lt;br /&gt;
  fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; f x.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.3. Definir la función&lt;br /&gt;
      dos : nat&lt;br /&gt;
   tal que dos es el número dos de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition dos : nat :=&lt;br /&gt;
  fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; f (f x).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.4. Definir la función&lt;br /&gt;
      cero : nat&lt;br /&gt;
   tal que cero es el número cero de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition cero : nat :=&lt;br /&gt;
  fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; x.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.5. Definir la función&lt;br /&gt;
      tres : nat&lt;br /&gt;
   tal que tres es el número tres de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition tres : nat := @aplica3veces.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.5. Definir la función&lt;br /&gt;
      suc (n : nat) : nat&lt;br /&gt;
   tal que (suc n) es el siguiente del número n de Church. Por ejemplo, &lt;br /&gt;
      suc cero = uno.&lt;br /&gt;
      suc uno  = dos.&lt;br /&gt;
      suc dos  = tres.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition suc (n : nat) : nat :=&lt;br /&gt;
   fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; f (n X f x).&lt;br /&gt;
&lt;br /&gt;
Example prop_suc_1: suc cero = uno.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_suc_2: suc uno = dos.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_suc_3: suc dos = tres.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.6. Definir la función&lt;br /&gt;
      suma (n m : nat) : nat&lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma cero uno            = uno.&lt;br /&gt;
      suma dos tres            = suma tres dos.&lt;br /&gt;
      suma (suma dos dos) tres = suma uno (suma tres tres).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition suma (n m : nat) : nat :=&lt;br /&gt;
  fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; m X f (n X f x).&lt;br /&gt;
&lt;br /&gt;
Example prop_suma_1 : suma cero uno = uno.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_suma_2 : suma dos tres = suma tres dos.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_suma_3 :&lt;br /&gt;
  suma (suma dos dos) tres = suma uno (suma tres tres).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.7. Definir la función&lt;br /&gt;
      producto (n m : nat) : nat&lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto uno uno               = uno.&lt;br /&gt;
      producto cero (suma tres tres) = cero.&lt;br /&gt;
      producto dos tres              = suma tres tres.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition producto (n m : nat) : nat :=&lt;br /&gt;
   fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; n X (m X f) x.&lt;br /&gt;
&lt;br /&gt;
Example prop_producto_1: producto uno uno = uno.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_producto_2: producto cero (suma tres tres) = cero.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_producto_3: producto dos tres = suma tres tres.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.11.8. Definir la función&lt;br /&gt;
      potencia (n m : nat) : nat&lt;br /&gt;
   tal que (potencia n m) es la potencia m-ésima de n. Por ejemplo, &lt;br /&gt;
      potencia dos dos   = suma dos dos.&lt;br /&gt;
      potencia tres dos  = suma (producto dos (producto dos dos)) uno.&lt;br /&gt;
      potencia tres cero = uno.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition potencia (n m : nat) : nat :=&lt;br /&gt;
  ( fun (X : Type) (f : X -&amp;gt; X) (x : X) =&amp;gt; (m (X -&amp;gt; X) (n X) f) x).&lt;br /&gt;
&lt;br /&gt;
Example prop_potencia_1: potencia dos dos = suma dos dos.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_potencia_2:&lt;br /&gt;
  potencia tres dos = suma (producto dos (producto dos dos)) uno.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_potencia_3: potencia tres cero = uno.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
End Church.&lt;br /&gt;
&lt;br /&gt;
End Exercises.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Bibliografía =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Poly.html Polymorphism and higher-order functions] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_4:_Polimorfismo_y_funciones_de_orden_superior_en_Coq&amp;diff=62</id>
		<title>Tema 4: Polimorfismo y funciones de orden superior en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_4:_Polimorfismo_y_funciones_de_orden_superior_en_Coq&amp;diff=62"/>
		<updated>2018-08-04T15:34:26Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página creada con «Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de * [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] de…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;br /&gt;
* [[Tema 4: Polimorfismo y funciones de orden superior en Coq]].&lt;br /&gt;
&lt;br /&gt;
=== Código ===&lt;br /&gt;
&lt;br /&gt;
El código correspondiente se encuentra en [https://github.com/jaalonso/DAOconCoq GitHub].&lt;br /&gt;
&lt;br /&gt;
=== Libro ===&lt;br /&gt;
&lt;br /&gt;
Todos los temas están recopilados en el libro [https://github.com/jaalonso/DAOconCoq/raw/master/texto/DAOconCoq.pdf Demostración asistida por ordenador con Coq].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=61</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=61"/>
		<updated>2018-08-04T15:34:03Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;br /&gt;
* [[Tema 4: Polimorfismo y funciones de orden superior en Coq]].&lt;br /&gt;
&lt;br /&gt;
=== Código ===&lt;br /&gt;
&lt;br /&gt;
El código correspondiente se encuentra en [https://github.com/jaalonso/DAOconCoq GitHub].&lt;br /&gt;
&lt;br /&gt;
=== Libro ===&lt;br /&gt;
&lt;br /&gt;
Todos los temas están recopilados en el libro [https://github.com/jaalonso/DAOconCoq/raw/master/texto/DAOconCoq.pdf Demostración asistida por ordenador con Coq].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=60</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=60"/>
		<updated>2018-08-03T10:54:05Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;br /&gt;
&lt;br /&gt;
=== Código ===&lt;br /&gt;
&lt;br /&gt;
El código correspondiente se encuentra en [https://github.com/jaalonso/DAOconCoq GitHub].&lt;br /&gt;
&lt;br /&gt;
=== Libro ===&lt;br /&gt;
&lt;br /&gt;
Todos los temas están recopilados en el libro [https://github.com/jaalonso/DAOconCoq/raw/master/texto/DAOconCoq.pdf Demostración asistida por ordenador con Coq].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_3:_Datos_estructurados_en_Coq&amp;diff=59</id>
		<title>Tema 3: Datos estructurados en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_3:_Datos_estructurados_en_Coq&amp;diff=59"/>
		<updated>2018-08-03T10:50:27Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: /* Teoría */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos cómo definir tipos de datos estructurados (como pares, listas, opcionales y diccionarios), definir funciones con los tipos definidos y demostrar propiedades de dichas dunciones. &lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Medio:T3_Listas.v|T3_Listas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T3: Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T2_Induccion.&lt;br /&gt;
&lt;br /&gt;
(* El contenido de la teoría es&lt;br /&gt;
   1. Pares de números &lt;br /&gt;
   2. Listas de números &lt;br /&gt;
      1. El tipo de la lista de números. &lt;br /&gt;
      2. La función repite (repeat)  &lt;br /&gt;
      3. La función longitud (length)  &lt;br /&gt;
      4. La función conc (app)  &lt;br /&gt;
      5. Las funciones primero (hd) y resto (tl)&lt;br /&gt;
      6. Ejercicios sobre listas de números &lt;br /&gt;
      7. Multiconjuntos como listas &lt;br /&gt;
   3. Razonamiento sobre listas&lt;br /&gt;
      1. Demostraciones por simplificación &lt;br /&gt;
      2. Demostraciones por casos &lt;br /&gt;
      3. Demostraciones por inducción&lt;br /&gt;
      4. Ejercicios &lt;br /&gt;
   4. Opcionales&lt;br /&gt;
   5. Diccionarios (o funciones parciales)&lt;br /&gt;
   6. Bibliografía&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Pares de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Se iniciar el módulo ListaNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module ListaNat. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Definir el tipo ProdNat para los pares de números&lt;br /&gt;
   naturales con el constructor&lt;br /&gt;
      par : nat -&amp;gt; nat -&amp;gt; ProdNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive ProdNat : Type :=&lt;br /&gt;
  par : nat -&amp;gt; nat -&amp;gt; ProdNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Calcular el tipo de la expresión (par 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (par 3 5).&lt;br /&gt;
(* ===&amp;gt; par 3 5 : ProdNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Definir la función&lt;br /&gt;
      fst : ProdNat -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | par x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Evaluar la expresión &lt;br /&gt;
      fst (par 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (fst (par 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5. Definir la función&lt;br /&gt;
      snd : ProdNat -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | par x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6. Definir la notación (x,y) como una abreviaura de &lt;br /&gt;
   (par x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (par x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.7. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.8. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.9. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.10. Definir la función&lt;br /&gt;
      intercambia : ProdNat -&amp;gt; ProdNat&lt;br /&gt;
   tal que (intercambia p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition intercambia (p : ProdNat) : ProdNat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.11. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem par_componentes1 : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.12. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem par_componentes2 : forall (p : ProdNat),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* &lt;br /&gt;
            ============================&lt;br /&gt;
            forall p : ProdNat, p = (fst p, snd p) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem par_componentes : forall (p : ProdNat),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.            (* p : ProdNat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          p = (fst p, snd p) *)&lt;br /&gt;
  destruct p as [n m]. (* n, m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          (n, m) = (fst (n, m), snd (n, m)) *)&lt;br /&gt;
  simpl.               (* (n, m) = (n, m) *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = intercambia p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ejercicio_1_1: forall p : ProdNat,&lt;br /&gt;
  (snd p, fst p) = intercambia p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro p.             (* p : ProdNat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          (snd p, fst p) = intercambia p *)&lt;br /&gt;
  destruct p as [n m]. (* n, m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          (snd (n, m), fst (n, m)) = intercambia (n, m) *)&lt;br /&gt;
  simpl.               (* (m, n) = (m, n) *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (intercambia p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ejercicio_1_2: forall p : ProdNat,&lt;br /&gt;
  fst (intercambia p) = snd p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro p.             (* p : ProdNat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          fst (intercambia p) = snd p *)&lt;br /&gt;
  destruct p as [n m]. (* n, m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          fst (intercambia (n, m)) = snd (n, m) *)&lt;br /&gt;
  simpl.               (* m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.1. El tipo de la lista de números. &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Definir el tipo ListaNat de la lista de los números&lt;br /&gt;
   naturales y cuyo constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive ListaNat : Type :=&lt;br /&gt;
  | nil  : ListaNat&lt;br /&gt;
  | cons : nat -&amp;gt; ListaNat -&amp;gt; ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Definir la constante &lt;br /&gt;
      ejLista : ListaNat&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ejLista := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.4. Definir la notación de las listas finitas escribiendo&lt;br /&gt;
   sus elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.5. Definir la lista cuyos elementos son 1, 2 y 3 mediante&lt;br /&gt;
   sistintas represerntaciones.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ejLista1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition ejLista2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition ejLista3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.2. La función repite (repeat)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Definir la función&lt;br /&gt;
      repite : nat -&amp;gt; nat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (repite n k) es la lista formada por k veces el número n. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      repite 5 3 = [5; 5; 5]&lt;br /&gt;
&lt;br /&gt;
   Nota: La función repite es quivalente a la predefinida repeat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repite (n k : nat) : ListaNat :=&lt;br /&gt;
  match k with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S k&amp;#039; =&amp;gt; n :: (repite n k&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (repite 5 3).&lt;br /&gt;
(* ===&amp;gt; [5; 5; 5] : ListaNat*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.3. La función longitud (length)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Definir la función&lt;br /&gt;
      longitud : ListaNat -&amp;gt; nat&lt;br /&gt;
   tal que (longitud xs) es el número de elementos de xs. Por ejemplo, &lt;br /&gt;
      longitud [4;2;6] = 3&lt;br /&gt;
&lt;br /&gt;
   Nota: La función longitud es equivalente a la predefinida length&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint longitud (l:ListaNat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (longitud t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (longitud [4;2;6]).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.4. La función conc (app)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.1. Definir la función&lt;br /&gt;
      conc : ListaNat -&amp;gt; ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (conc xs ys) es la concatenación de xs e ys. Por ejemplo, &lt;br /&gt;
      conc [1;3] [4;2;3;5] =  [1; 3; 4; 2; 3; 5]&lt;br /&gt;
&lt;br /&gt;
   Nota:La función conc es equivalente a la predefinida app.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint conc (xs ys : ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; ys&lt;br /&gt;
  | x :: zs =&amp;gt; x :: (conc zs ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (conc [1;3] [4;2;3;5]).&lt;br /&gt;
(* ===&amp;gt; [1; 3; 4; 2; 3; 5] : ListaNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.2. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (conc xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (conc x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.3. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_conc1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_conc2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_conc3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.5. Las funciones primero (hd) y resto (tl)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.1. Definir la función&lt;br /&gt;
      primero : nat -&amp;gt; ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (primero d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. Por ejemplo,&lt;br /&gt;
      primero 7 [3;2;5] = 3 &lt;br /&gt;
      primero 7 []      = 7 &lt;br /&gt;
&lt;br /&gt;
   Nota. La función primero es equivalente a la predefinida hd&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition primero (d : nat) (xs : ListaNat) : nat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil     =&amp;gt; d&lt;br /&gt;
  | y :: ys =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (primero 7 [3;2;5]).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
Compute (primero 7 []).&lt;br /&gt;
(* ===&amp;gt; 7 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.2. Demostrar que &lt;br /&gt;
       primero 0 [1;2;3] = 1.&lt;br /&gt;
       resto [1;2;3]     = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example prop_primero1: primero 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primero2: primero 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.3. Definir la función&lt;br /&gt;
      resto : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (resto xs) es el resto de xs. Por ejemplo.&lt;br /&gt;
      resto [3;2;5] = [2; 5]&lt;br /&gt;
      resto []      = [ ]&lt;br /&gt;
&lt;br /&gt;
   Nota. La función resto es equivalente la predefinida tl.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition resto (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil     =&amp;gt; nil&lt;br /&gt;
  | y :: ys =&amp;gt; ys&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (resto [3;2;5]).&lt;br /&gt;
(* ===&amp;gt; [2; 5] : ListaNat *)&lt;br /&gt;
Compute (resto []).&lt;br /&gt;
(* ===&amp;gt; [ ] : ListaNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.4. Demostrar que &lt;br /&gt;
       resto [1;2;3] = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example prop_resto: resto [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.6. Ejercicios sobre listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.1. Definir la función&lt;br /&gt;
      noCeros : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (noCeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      noCeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint noCeros (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; noCeros bs &lt;br /&gt;
            | _ =&amp;gt;  a :: noCeros bs&lt;br /&gt;
            end&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Compute (noCeros [0;1;0;2;3;0;0]).&lt;br /&gt;
(* ===&amp;gt; [1; 2; 3] : ListaNat  *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.2. Definir la función&lt;br /&gt;
      impares : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (impares xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      impares [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint impares (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil   =&amp;gt; nil&lt;br /&gt;
  | y::ys =&amp;gt; if esImpar y&lt;br /&gt;
             then y :: impares ys &lt;br /&gt;
             else impares ys&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Compute (impares [0;1;0;2;3;0;0]).&lt;br /&gt;
(* ===&amp;gt; [1; 3] : ListaNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.3. Definir la función&lt;br /&gt;
      nImpares : ListaNat -&amp;gt; nat&lt;br /&gt;
   tal que (nImpares xs) es el número de elementos impares de xs. Por &lt;br /&gt;
   ejemplo,&lt;br /&gt;
      nImpares [1;0;3;1;4;5] = 4.&lt;br /&gt;
      nImpares [0;2;4]       = 0.&lt;br /&gt;
      nImpares nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nImpares (xs:ListaNat) : nat :=&lt;br /&gt;
  longitud (impares xs). &lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares1: nImpares [1;0;3;1;4;5] = 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares2: nImpares [0;2;4] = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares3: nImpares nil = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.4. Definir la función&lt;br /&gt;
      intercaladas : ListaNat -&amp;gt; ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (intercaladas xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      intercaladas [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      intercaladas [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      intercaladas [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      intercaladas [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint intercaladas (xs ys : ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; ys&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; match ys with&lt;br /&gt;
              | nil    =&amp;gt; xs&lt;br /&gt;
              | y::ys&amp;#039; =&amp;gt; x::y::intercaladas xs&amp;#039; ys&amp;#039;&lt;br /&gt;
              end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas1: intercaladas [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas2: intercaladas [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas3: intercaladas [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas4: intercaladas [] [20;30] = [20;30].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.7. Multiconjuntos como listas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.7.1. Un multiconjunto es una colección de elementos donde&lt;br /&gt;
   no importa el orden de los elementos, pero sí el número de&lt;br /&gt;
   ocurrencias de cada elemento.&lt;br /&gt;
&lt;br /&gt;
   Definir el tipo multiconjunto de los multiconjuntos de números&lt;br /&gt;
   naturales. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition multiconjunto := ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.2. Definir la función&lt;br /&gt;
      nOcurrencias : nat -&amp;gt; multiconjunto -&amp;gt; nat &lt;br /&gt;
   tal que (nOcurrencias x ys) es el número de veces que aparece el&lt;br /&gt;
   elemento x en el multiconjunto ys. Por ejemplo,&lt;br /&gt;
      nOcurrencias 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
      nOcurrencias 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nOcurrencias (x:nat) (ys:multiconjunto) : nat :=&lt;br /&gt;
  match ys with&lt;br /&gt;
  | nil    =&amp;gt; 0&lt;br /&gt;
  | y::ys&amp;#039; =&amp;gt; if iguales_nat y x&lt;br /&gt;
              then 1 + nOcurrencias x ys&amp;#039;&lt;br /&gt;
              else nOcurrencias x ys&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_nOcurrencias1: nOcurrencias 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nOcurrencias2: nOcurrencias 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
Proof. reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.3. Definir la función&lt;br /&gt;
      suma : multiconjunto -&amp;gt; multiconjunto -&amp;gt; multiconjunto&lt;br /&gt;
   tal que (suma xs ys) es la suma de los multiconjuntos xs e ys. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      suma [1;2;3] [1;4;1]                  = [1; 2; 3; 1; 4; 1]&lt;br /&gt;
      nOcurrencias 1 (suma [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition suma : multiconjunto -&amp;gt; multiconjunto -&amp;gt; multiconjunto :=&lt;br /&gt;
  conc.&lt;br /&gt;
&lt;br /&gt;
Example prop_sum: nOcurrencias 1 (suma [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.4. Definir la función&lt;br /&gt;
      agrega : nat -&amp;gt; multiconjunto -&amp;gt; multiconjunto &lt;br /&gt;
   tal que (agrega x ys) es el multiconjunto obtenido añadiendo el&lt;br /&gt;
   elemento x al multiconjunto ys. Por ejemplo,&lt;br /&gt;
      nOcurrencias 1 (agrega 1 [1;4;1]) = 3.&lt;br /&gt;
      nOcurrencias 5 (agrega 1 [1;4;1]) = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition agrega (x:nat) (ys:multiconjunto) : multiconjunto :=&lt;br /&gt;
  x :: ys.&lt;br /&gt;
&lt;br /&gt;
Example prop_agrega1: nOcurrencias 1 (agrega 1 [1;4;1]) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_agrega2: nOcurrencias 5 (agrega 1 [1;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.5. Definir la función&lt;br /&gt;
      pertenece : nat -&amp;gt; multiconjunto -&amp;gt; bool&lt;br /&gt;
   tal que (pertenece x ys) se verfica si x pertenece al multiconjunto&lt;br /&gt;
   ys. Por ejemplo,  &lt;br /&gt;
      pertenece 1 [1;4;1] = true.&lt;br /&gt;
      pertenece 2 [1;4;1] = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pertenece (x:nat) (ys:multiconjunto) : bool := &lt;br /&gt;
  negacion (iguales_nat 0 (nOcurrencias x ys)).&lt;br /&gt;
&lt;br /&gt;
Example prop_pertenece1: pertenece 1 [1;4;1] = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_pertenece2: pertenece 2 [1;4;1] = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.6. Definir la función&lt;br /&gt;
      eliminaUna : nat -&amp;gt; multiconjunto -&amp;gt; multiconjunto&lt;br /&gt;
   tal que (eliminaUna x ys) es el multiconjunto obtenido eliminando una&lt;br /&gt;
   ocurrencia de x en el multiconjunto ys. Por ejemplo, &lt;br /&gt;
      nOcurrencias 5 (eliminaUna 5 [2;1;5;4;1])     = 0.&lt;br /&gt;
      nOcurrencias 4 (eliminaUna 5 [2;1;4;5;1;4])   = 2.&lt;br /&gt;
      nOcurrencias 5 (eliminaUna 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint eliminaUna (x:nat) (ys:multiconjunto) : multiconjunto :=&lt;br /&gt;
  match ys with&lt;br /&gt;
  | nil      =&amp;gt; nil&lt;br /&gt;
  | y :: ys&amp;#039; =&amp;gt; if iguales_nat y x&lt;br /&gt;
               then ys&amp;#039;&lt;br /&gt;
               else y :: eliminaUna x ys&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna1: nOcurrencias 5 (eliminaUna 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna2: nOcurrencias 5 (eliminaUna 5 [2;1;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna3: nOcurrencias 4 (eliminaUna 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna4: nOcurrencias 5 (eliminaUna 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.7. Definir la función&lt;br /&gt;
      eliminaTodas : nat -&amp;gt; multiconjunto -&amp;gt; multiconjunto&lt;br /&gt;
   tal que (eliminaTodas x ys) es el multiconjunto obtenido eliminando&lt;br /&gt;
   todas las ocurrencias de x en el multiconjunto ys. Por ejemplo,&lt;br /&gt;
      nOcurrencias 5 (eliminaTodas 5 [2;1;5;4;1])           = 0.&lt;br /&gt;
      nOcurrencias 5 (eliminaTodas 5 [2;1;4;1])             = 0.&lt;br /&gt;
      nOcurrencias 4 (eliminaTodas 5 [2;1;4;5;1;4])         = 2.&lt;br /&gt;
      nOcurrencias 5 (eliminaTodas 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint eliminaTodas (x:nat) (ys:multiconjunto) : multiconjunto :=&lt;br /&gt;
  match ys with&lt;br /&gt;
  | nil      =&amp;gt; nil&lt;br /&gt;
  | y :: ys&amp;#039; =&amp;gt; if iguales_nat y x&lt;br /&gt;
               then eliminaTodas x ys&amp;#039;&lt;br /&gt;
               else y :: eliminaTodas x ys&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas1: nOcurrencias 5 (eliminaTodas 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas2: nOcurrencias 5 (eliminaTodas 5 [2;1;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas3: nOcurrencias 4 (eliminaTodas 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas4: nOcurrencias 5 (eliminaTodas 5 [1;5;4;5;4;5;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.8. Definir la función&lt;br /&gt;
      submulticonjunto : multiconjunto -&amp;gt; multiconjunto -&amp;gt; bool&lt;br /&gt;
   tal que (submulticonjunto xs ys) se verifica si xs es un&lt;br /&gt;
   submulticonjunto de ys. Por ejemplo,&lt;br /&gt;
      submulticonjunto [1;2]   [2;1;4;1] = true.&lt;br /&gt;
      submulticonjunto [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint submulticonjunto (xs:multiconjunto) (ys:multiconjunto) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; pertenece x ys &amp;amp;&amp;amp; submulticonjunto xs&amp;#039; (eliminaUna x ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_submulticonjunto1: submulticonjunto [1;2] [2;1;4;1] = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_submulticonjunto2: submulticonjunto [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.9. Escribir una propiedad sobre multiconjuntos con las&lt;br /&gt;
   funciones nOcurrencias y agrega y demostrarla. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nOcurrencias_conc: forall xs ys : multiconjunto, forall n:nat,&lt;br /&gt;
  nOcurrencias n (conc xs ys) = nOcurrencias n xs + nOcurrencias n ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys n.               (* xs, ys : multiconjunto&lt;br /&gt;
                                   n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   nOcurrencias n (xs ++ ys) = &lt;br /&gt;
                                    nOcurrencias n xs + nOcurrencias n ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].&lt;br /&gt;
  -                             (* ys : multiconjunto&lt;br /&gt;
                                   n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   nOcurrencias n ([ ] ++ ys) = &lt;br /&gt;
                                    nOcurrencias n [ ] + nOcurrencias n ys *)&lt;br /&gt;
    simpl.                      (* nOcurrencias n ys = nOcurrencias n ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039; : ListaNat&lt;br /&gt;
                                   ys : multiconjunto&lt;br /&gt;
                                   n : nat&lt;br /&gt;
                                   HI : nOcurrencias n (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                        nOcurrencias n xs&amp;#039; + nOcurrencias n ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   nOcurrencias n ((x :: xs&amp;#039;) ++ ys) =&lt;br /&gt;
                                    nOcurrencias n (x :: xs&amp;#039;) + &lt;br /&gt;
                                    nOcurrencias n ys *)&lt;br /&gt;
    simpl.                      (* (if iguales_nat x n&lt;br /&gt;
                                    then S (nOcurrencias n (xs&amp;#039; ++ ys))&lt;br /&gt;
                                    else nOcurrencias n (xs&amp;#039; ++ ys)) =&lt;br /&gt;
                                   (if iguales_nat x n &lt;br /&gt;
                                    then S (nOcurrencias n xs&amp;#039;) &lt;br /&gt;
                                    else nOcurrencias n xs&amp;#039;) +&lt;br /&gt;
                                   nOcurrencias n ys  *)&lt;br /&gt;
    destruct (iguales_nat x n). &lt;br /&gt;
    +                           (* S (nOcurrencias n (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                   S (nOcurrencias n xs&amp;#039;) + &lt;br /&gt;
                                   nOcurrencias n ys *)&lt;br /&gt;
      simpl.                    (* S (nOcurrencias n (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                   S (nOcurrencias n xs&amp;#039; + &lt;br /&gt;
                                      nOcurrencias n ys) *)&lt;br /&gt;
      rewrite HI.               (* S (nOcurrencias n xs&amp;#039; + nOcurrencias n ys) =&lt;br /&gt;
                                   S (nOcurrencias n xs&amp;#039; + nOcurrencias n ys) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* nOcurrencias n (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                   nOcurrencias n xs&amp;#039; + nOcurrencias n ys *)&lt;br /&gt;
      rewrite HI.               (* nOcurrencias n xs&amp;#039; + nOcurrencias n ys =&lt;br /&gt;
                                   nOcurrencias n xs&amp;#039; + nOcurrencias n ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Razonamiento sobre listas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.1. Demostrar que, para toda lista de naturales xs,&lt;br /&gt;
      [] ++ xs = xs&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_conc : forall xs:ListaNat,&lt;br /&gt;
  [] ++ xs = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.2. Demostraciones por casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2.1. Demostrar que, para toda lista de naturales xs,&lt;br /&gt;
      pred (longitud xs) = longitud (resto xs)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem resto_longitud_pred : forall xs:ListaNat,&lt;br /&gt;
  pred (longitud xs) = longitud (resto xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.                (* xs : ListaNat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Nat.pred (longitud xs) = longitud (resto xs) *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                         (* &lt;br /&gt;
                               ============================&lt;br /&gt;
                               Nat.pred (longitud []) = longitud (resto []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                         (* x : nat&lt;br /&gt;
                               xs&amp;#039; : ListaNat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Nat.pred (longitud (x :: xs&amp;#039;)) = &lt;br /&gt;
                                longitud (resto (x :: xs&amp;#039;)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.3. Demostraciones por inducción&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3.1. Demostrar que la concatenación de listas de naturales&lt;br /&gt;
   es asociativa; es decir,&lt;br /&gt;
      (xs ++ ys) ++ zs = xs ++ (ys ++ zs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_asociativa: forall xs ys zs : ListaNat,&lt;br /&gt;
  (xs ++ ys) ++ zs = xs ++ (ys ++ zs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys zs.             (* xs, ys, zs : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (xs ++ ys) ++ zs = xs ++ (ys ++ zs) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* ys, zs : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  ([ ] ++ ys) ++ zs = [ ] ++ (ys ++ zs) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039;, ys, zs : ListaNat&lt;br /&gt;
                                  HI : (xs&amp;#039; ++ ys) ++ zs = xs&amp;#039; ++ (ys ++ zs)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  ((x :: xs&amp;#039;) ++ ys) ++ zs = &lt;br /&gt;
                                   (x :: xs&amp;#039;) ++ (ys ++ zs) *)&lt;br /&gt;
    simpl.                     (* (x :: (xs&amp;#039; ++ ys)) ++ zs = &lt;br /&gt;
                                  x :: (xs&amp;#039; ++ (ys ++ zs)) *)&lt;br /&gt;
    rewrite -&amp;gt; HI.             (* x :: (xs&amp;#039; ++ (ys ++ zs)) = &lt;br /&gt;
                                  x :: (xs&amp;#039; ++ (ys ++ zs)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3.2. Definir la función&lt;br /&gt;
      inversa : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (inversa xs) es la inversa de xs. Por ejemplo,&lt;br /&gt;
      inversa [1;2;3] = [3;2;1].&lt;br /&gt;
      inversa nil     = nil.&lt;br /&gt;
&lt;br /&gt;
   Nota. La función inversa es equivalente a la predefinida rev.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint inversa (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; inversa xs&amp;#039; ++ [x]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_inversa1: inversa [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_inversa2: inversa nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3.3. Demostrar que&lt;br /&gt;
      longitud (inversa xs) = longitud xs&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem longitud_inversa1: forall xs:ListaNat,&lt;br /&gt;
  longitud (inversa xs) = longitud xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (inversa [ ]) = longitud [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039; : ListaNat&lt;br /&gt;
                                  HI : longitud (inversa xs&amp;#039;) = longitud xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (inversa (x :: xs&amp;#039;)) = &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* longitud (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                   S (longitud xs&amp;#039;)*)&lt;br /&gt;
    rewrite &amp;lt;- HI.             (* longitud (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                   S (longitud (inversa xs&amp;#039;)) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* Nota: Para simplificar la última expresión se necesita el siguiente lema. *)&lt;br /&gt;
&lt;br /&gt;
Lemma longitud_conc : forall xs ys : ListaNat,&lt;br /&gt;
  longitud (xs ++ ys) = longitud xs + longitud ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys.                 (* xs, ys : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (xs ++ ys) = &lt;br /&gt;
                                    longitud xs + longitud ys *)&lt;br /&gt;
  induction xs as [| x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* ys : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud ([ ] ++ ys) = &lt;br /&gt;
                                    longitud [ ] + longitud ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039;, ys : ListaNat&lt;br /&gt;
                                   HI : longitud (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                         longitud xs&amp;#039; + longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) + longitud ys *)&lt;br /&gt;
    simpl.                      (* S (longitud (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                   S (longitud xs&amp;#039; + longitud ys) *)&lt;br /&gt;
    rewrite -&amp;gt; HI.              (* S (longitud xs&amp;#039; + longitud ys) = &lt;br /&gt;
                                   S (longitud xs&amp;#039; + longitud ys) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem longitud_inversa : forall xs:ListaNat,&lt;br /&gt;
  longitud (inversa xs) = longitud xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.                    (* xs : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (inversa xs) = longitud xs *)&lt;br /&gt;
  induction xs as [| x xs&amp;#039; HI].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (inversa [ ]) = longitud [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039; : ListaNat&lt;br /&gt;
                                   HI : longitud (inversa xs&amp;#039;) = longitud xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (inversa (x :: xs&amp;#039;)) = &lt;br /&gt;
                                    longitud (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* longitud (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                   S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite longitud_conc.      (* longitud (inversa xs&amp;#039;) + longitud [x] = &lt;br /&gt;
                                   S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite HI.                 (* longitud xs&amp;#039; + longitud [x] = &lt;br /&gt;
                                   S (longitud xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* longitud xs&amp;#039; + 1 = S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite suma_conmutativa.   (* 1 + longitud xs&amp;#039; = S (longitud xs&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.4. Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.1. Demostrar que la lista vacía es el elemento neutro&lt;br /&gt;
   por la derecha de la concatenación de listas. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_nil: forall xs:ListaNat,&lt;br /&gt;
  xs ++ [] = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.                    (* xs : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   xs ++ [ ] = xs *)&lt;br /&gt;
  induction xs as [| x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   [ ] ++ [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039; : ListaNat&lt;br /&gt;
                                   HI : xs&amp;#039; ++ [ ] = xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (x :: xs&amp;#039;) ++ [ ] = x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                      (* x :: (xs&amp;#039; ++ [ ]) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                 (* x :: xs&amp;#039; = x :: xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.2. Demostrar que inversa es un endomorfismo en &lt;br /&gt;
   (ListaNat,++); es decir,&lt;br /&gt;
      inversa (xs ++ ys) = inversa ys ++ inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_conc: forall xs ys : ListaNat,&lt;br /&gt;
  inversa (xs ++ ys) = inversa ys ++ inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys.                (* xs, ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (xs ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa ([ ] ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa [ ] *)&lt;br /&gt;
    simpl.                     (* inversa ys = inversa ys ++ [ ] *)&lt;br /&gt;
    rewrite conc_nil.          (* inversa ys = inversa ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039;, ys : ListaNat&lt;br /&gt;
                                  HI : inversa (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       inversa ys ++ inversa xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* inversa (xs&amp;#039; ++ ys) ++ [x] = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    rewrite HI.                (* (inversa ys ++ inversa xs&amp;#039;) ++ [x] = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    rewrite conc_asociativa.   (* inversa ys ++ (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.3. Demostrar que inversa es involutiva; es decir,&lt;br /&gt;
      inversa (inversa xs) = xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_involutiva: forall xs:ListaNat,&lt;br /&gt;
  inversa (inversa xs) = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa [ ]) = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039; : ListaNat&lt;br /&gt;
                                  HI : inversa (inversa xs&amp;#039;) = xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa (x :: xs&amp;#039;)) = x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                     (* inversa (inversa xs&amp;#039; ++ [x]) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite inversa_conc.      (* inversa [x] ++ inversa (inversa xs&amp;#039;) = &lt;br /&gt;
                                  x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                     (* x :: inversa (inversa xs&amp;#039;) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                (* x :: xs&amp;#039; = x :: xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.4. Demostrar que&lt;br /&gt;
      xs ++ (ys ++ (zs ++ vs)) = ((xs ++ ys) ++ zs) ++ vs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_asociativa4 : forall xs ys zs vs : ListaNat,&lt;br /&gt;
  xs ++ (ys ++ (zs ++ vs)) = ((xs ++ ys) ++ zs) ++ vs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys zs vs.      (* xs, ys, zs, vs : ListaNat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs ++ (ys ++ (zs ++ vs)) = &lt;br /&gt;
                              ((xs ++ ys) ++ zs) ++ vs *)&lt;br /&gt;
  rewrite conc_asociativa. (* xs ++ (ys ++ (zs ++ vs)) = &lt;br /&gt;
                              (xs ++ ys) ++ (zs ++ vs) *)&lt;br /&gt;
  rewrite conc_asociativa. (* xs ++ (ys ++ (zs ++ vs)) =&lt;br /&gt;
                              xs ++ (ys ++ (zs ++ vs)) *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.5. Demostrar que al concatenar dos listas no aparecen ni&lt;br /&gt;
   desaparecen ceros. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma noCeros_conc : forall xs ys : ListaNat,&lt;br /&gt;
  noCeros (xs ++ ys) = (noCeros xs) ++ (noCeros ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys.                (* xs, ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  noCeros (xs ++ ys) = &lt;br /&gt;
                                  noCeros xs ++ noCeros ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  noCeros ([] ++ ys) = &lt;br /&gt;
                                  noCeros [] ++ noCeros ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039;, ys : ListaNat&lt;br /&gt;
                                  HI : noCeros (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       noCeros xs&amp;#039; ++ noCeros ys&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  noCeros ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  noCeros (x :: xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
    destruct x.&lt;br /&gt;
    +                          (* noCeros ((0 :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  noCeros (0 :: xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      simpl.                   (* noCeros (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                  noCeros xs&amp;#039; ++ noCeros ys *)&lt;br /&gt;
      rewrite HI.              (* noCeros xs&amp;#039; ++ noCeros ys = &lt;br /&gt;
                                  noCeros xs&amp;#039; ++ noCeros ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* noCeros ((S x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  noCeros (S x :: xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      simpl.                   (* S x :: noCeros (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                  (S x :: noCeros xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      rewrite HI.              (* S x :: (noCeros xs&amp;#039; ++ noCeros ys) = &lt;br /&gt;
                                  (S x :: noCeros xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.6. Definir la función&lt;br /&gt;
      iguales_lista : ListaNat -&amp;gt; ListaNat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_lista xs ys) se verifica si las listas xs e ys son&lt;br /&gt;
   iguales. Por ejemplo,&lt;br /&gt;
      iguales_lista nil nil         = true.&lt;br /&gt;
      iguales_lista [1;2;3] [1;2;3] = true.&lt;br /&gt;
      iguales_lista [1;2;3] [1;2;4] = false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_lista (xs ys : ListaNat) : bool:=&lt;br /&gt;
  match xs, ys with&lt;br /&gt;
  | nil,    nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039;, y::ys&amp;#039; =&amp;gt; iguales_nat x y &amp;amp;&amp;amp; iguales_lista xs&amp;#039; ys&amp;#039;&lt;br /&gt;
  | _, _           =&amp;gt; false&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Example prop_iguales_lista1: (iguales_lista nil nil = true).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_iguales_lista2: iguales_lista [1;2;3] [1;2;3] = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_iguales_lista3: iguales_lista [1;2;3] [1;2;4] = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.7. Demostrar que la igualdad de listas cumple la&lt;br /&gt;
   propiedad reflexiva. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_lista_refl : forall xs:ListaNat,&lt;br /&gt;
  iguales_lista xs xs = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  iguales_lista [ ] [ ] = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039; : ListaNat&lt;br /&gt;
                                  HI : iguales_lista xs&amp;#039; xs&amp;#039; = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  iguales_lista (x :: xs&amp;#039;) (x :: xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                     (* iguales_nat x x &amp;amp;&amp;amp; &lt;br /&gt;
                                  iguales_lista xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    rewrite HI.                (* iguales_nat x x &amp;amp;&amp;amp; true = true *)&lt;br /&gt;
    rewrite iguales_nat_refl.  (* true &amp;amp;&amp;amp; true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.8. Demostrar que al incluir un elemento en un&lt;br /&gt;
   multiconjunto, ese elemento aparece al menos una vez en el&lt;br /&gt;
   resultado. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nOcurrencias_agrega: forall (x:nat) (xs:multiconjunto),&lt;br /&gt;
  menor_o_igual 1 (nOcurrencias x (agrega x xs)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x xs.              (* x : nat&lt;br /&gt;
                               xs : multiconjunto&lt;br /&gt;
                               ============================&lt;br /&gt;
                               menor_o_igual 1 (nOcurrencias x (agrega x xs)) =&lt;br /&gt;
                               true *)&lt;br /&gt;
  simpl.                    (* match&lt;br /&gt;
                                (if iguales_nat x x then S (nOcurrencias x xs) &lt;br /&gt;
                                                    else nOcurrencias x xs)&lt;br /&gt;
                                with&lt;br /&gt;
                                | 0 =&amp;gt; false&lt;br /&gt;
                                | S _ =&amp;gt; true&lt;br /&gt;
                                end = &lt;br /&gt;
                               true *)&lt;br /&gt;
  rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.9. Demostrar que cada número natural es menor o igual&lt;br /&gt;
   que su siguiente. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_n_Sn: forall n:nat,&lt;br /&gt;
  menor_o_igual n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                (* n : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              menor_o_igual n (S n) = true *)&lt;br /&gt;
  induction n as [|n&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              menor_o_igual 0 1 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* n&amp;#039; : nat&lt;br /&gt;
                              HI : menor_o_igual n&amp;#039; (S n&amp;#039;) = true&lt;br /&gt;
                              ============================&lt;br /&gt;
                              menor_o_igual (S n&amp;#039;) (S (S n&amp;#039;)) = true *)&lt;br /&gt;
    simpl.                 (* menor_o_igual n&amp;#039; (S n&amp;#039;) = true *)&lt;br /&gt;
    rewrite HI.            (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.10. Demostrar que al borrar una ocurrencia de 0 de un&lt;br /&gt;
   multiconjunto el número de ocurrencias de 0 en el resultado es menor&lt;br /&gt;
   o igual que en el original.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_nOcurrencias: forall (xs : multiconjunto),&lt;br /&gt;
  menor_o_igual (nOcurrencias 0 (eliminaUna 0 xs)) (nOcurrencias 0 xs) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].&lt;br /&gt;
  -                               (* &lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     menor_o_igual (nOcurrencias 0 (eliminaUna 0 [])) &lt;br /&gt;
                                                   (nOcurrencias 0 []) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                               (* x : nat&lt;br /&gt;
                                     xs&amp;#039; : ListaNat&lt;br /&gt;
                                     HI: menor_o_igual (nOcurrencias 0 (eliminaUna 0 xs&amp;#039;))&lt;br /&gt;
                                                        (nOcurrencias 0 xs&amp;#039;) &lt;br /&gt;
                                         = true &lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     menor_o_igual (nOcurrencias 0 (eliminaUna 0 (x::xs&amp;#039;)))&lt;br /&gt;
                                                    (nOcurrencias 0 (x :: xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
    destruct x.&lt;br /&gt;
    +                             (* menor_o_igual (nOcurrencias 0 (eliminaUna 0 (0::xs&amp;#039;)))&lt;br /&gt;
                                                   (nOcurrencias 0 (0 :: xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      simpl.                      (* menor_o_igual (nOcurrencias 0 xs&amp;#039;) &lt;br /&gt;
                                                   (S (nOcurrencias 0 xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      rewrite menor_o_igual_n_Sn. (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                             (* menor_o_igual (nOcurrencias 0 &lt;br /&gt;
                                                     (eliminaUna 0 (S x :: xs&amp;#039;)))&lt;br /&gt;
                                                   (nOcurrencias 0 (S x :: xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      simpl.                      (* menor_o_igual (nOcurrencias 0 (eliminaUna 0 xs&amp;#039;)) &lt;br /&gt;
                                                   (nOcurrencias 0 xs&amp;#039;) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      rewrite HI.                 (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.11. Escribir un teorema con las funciones nOcurrencias&lt;br /&gt;
   y suma de los multiconjuntos. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nOcurrencias_suma:&lt;br /&gt;
  forall x : nat, forall xs ys : multiconjunto,&lt;br /&gt;
   nOcurrencias x (suma xs ys) = nOcurrencias x xs + nOcurrencias x ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x xs ys.                (* x : nat&lt;br /&gt;
                                    xs, ys : multiconjunto&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    nOcurrencias x (suma xs ys) = &lt;br /&gt;
                                    nOcurrencias x xs + nOcurrencias x ys *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].&lt;br /&gt;
  -                              (* x : nat&lt;br /&gt;
                                    ys : multiconjunto&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    nOcurrencias x (suma [ ] ys) = &lt;br /&gt;
                                    nOcurrencias x [ ] + nOcurrencias x ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* x, x&amp;#039; : nat&lt;br /&gt;
                                    xs&amp;#039; : ListaNat&lt;br /&gt;
                                    ys : multiconjunto&lt;br /&gt;
                                    HI : nOcurrencias x (suma xs&amp;#039; ys) = &lt;br /&gt;
                                         nOcurrencias x xs&amp;#039; + nOcurrencias x ys&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    nOcurrencias x (suma (x&amp;#039; :: xs&amp;#039;) ys) = &lt;br /&gt;
                                    nOcurrencias x (x&amp;#039; :: xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
    simpl.                       (* (if iguales_nat x&amp;#039; x&lt;br /&gt;
                                        then S (nOcurrencias x (suma xs&amp;#039; ys))&lt;br /&gt;
                                        else nOcurrencias x (suma xs&amp;#039; ys)) &lt;br /&gt;
                                    =&lt;br /&gt;
                                    (if iguales_nat x&amp;#039; x &lt;br /&gt;
                                        then S (nOcurrencias x xs&amp;#039;) &lt;br /&gt;
                                        else nOcurrencias x xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
    destruct (iguales_nat x&amp;#039; x). &lt;br /&gt;
    +                            (* S (nOcurrencias x (suma xs&amp;#039; ys)) = &lt;br /&gt;
                                    S (nOcurrencias x xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
      rewrite HI.                (* S (nOcurrencias x xs&amp;#039; + nOcurrencias x ys) = &lt;br /&gt;
                                    S (nOcurrencias x xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* nOcurrencias x (suma xs&amp;#039; ys) = &lt;br /&gt;
                                    nOcurrencias x xs&amp;#039; + nOcurrencias x ys *)&lt;br /&gt;
      rewrite HI.                (* nOcurrencias x xs&amp;#039; + nOcurrencias x ys = &lt;br /&gt;
                                    nOcurrencias x xs&amp;#039; + nOcurrencias x ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.12. Demostrar que la función inversa es inyectiva; es&lt;br /&gt;
   decir, &lt;br /&gt;
      forall (xs ys : ListaNat), inversa xs = inversa ys -&amp;gt; xs = ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_inyectiva: forall (xs ys : ListaNat),&lt;br /&gt;
  inversa xs = inversa ys -&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.                (* xs, ys : ListaNat&lt;br /&gt;
                                    H : inversa xs = inversa ys&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    xs = ys *)&lt;br /&gt;
  rewrite &amp;lt;- inversa_involutiva. (* xs = inversa (inversa ys) *)&lt;br /&gt;
  rewrite &amp;lt;- H.                  (* xs = inversa (inversa xs) *)&lt;br /&gt;
  rewrite inversa_involutiva.    (* xs = xs *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Opcionales&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Definir el tipo OpcionalNat con los contructores&lt;br /&gt;
      Some : nat -&amp;gt; OpcionalNat&lt;br /&gt;
      None : OpcionalNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive OpcionalNat : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; OpcionalNat&lt;br /&gt;
  | None : OpcionalNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.2. Definir la función&lt;br /&gt;
      nthOpcional : ListaNat -&amp;gt; nat -&amp;gt; OpcionalNat&lt;br /&gt;
   tal que (nthOpcional xs n) es el n-ésimo elemento de la lista xs o None&lt;br /&gt;
   si la lista tiene menos de n elementos. Por ejemplo,&lt;br /&gt;
      nthOpcional [4;5;6;7] 0 = Some 4.&lt;br /&gt;
      nthOpcional [4;5;6;7] 3 = Some 7.&lt;br /&gt;
      nthOpcional [4;5;6;7] 9 = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nthOpcional (xs:ListaNat) (n:nat) : OpcionalNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; None&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; match iguales_nat n O with&lt;br /&gt;
                | true  =&amp;gt; Some x&lt;br /&gt;
                | false =&amp;gt; nthOpcional xs&amp;#039; (pred n)&lt;br /&gt;
                end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional1 : nthOpcional [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional2 : nthOpcional [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional3 : nthOpcional [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* Introduciendo condicionales nos queda: *)&lt;br /&gt;
Fixpoint nthOpcional&amp;#039; (xs:ListaNat) (n:nat) : OpcionalNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; None&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; if iguales_nat x O&lt;br /&gt;
                then Some x&lt;br /&gt;
                else nthOpcional&amp;#039; xs&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.3. Definir la función&lt;br /&gt;
      eliminaOpcionalNat -&amp;gt; OpcionalNat -&amp;gt; nat&lt;br /&gt;
   tal que (option_elim d o) es el valor de o, si o tiene valor o es d&lt;br /&gt;
   en caso contrario. Por ejemplo,&lt;br /&gt;
      eliminaOpcionalNat 3 (Some 7) = 7&lt;br /&gt;
      eliminaOpcionalNat 3 None     = 3&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition eliminaOpcionalNat (d : nat) (o : OpcionalNat) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None    =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (eliminaOpcionalNat 3 (Some 7)).&lt;br /&gt;
(* ===&amp;gt; 7 : nat *)&lt;br /&gt;
Compute (eliminaOpcionalNat 3 None).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Definir la función&lt;br /&gt;
      primeroOpcional : ListaNat -&amp;gt; OpcionalNat&lt;br /&gt;
   tal que (primeroOpcional xs) es el primer elemento de xs, si xs es no&lt;br /&gt;
   vacía; o es None, en caso contrario. Por ejemplo,&lt;br /&gt;
      primeroOpcional []    = None.&lt;br /&gt;
      primeroOpcional [1]   = Some 1.&lt;br /&gt;
      primeroOpcional [5;6] = Some 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition primeroOpcional (xs : ListaNat) : OpcionalNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; None&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; Some x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional1 : primeroOpcional [] = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional2 : primeroOpcional [1] = Some 1.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional3 : primeroOpcional [5;6] = Some 5.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.2. Demostrar que&lt;br /&gt;
      primero d xs = eliminaOpcionalNat d (primeroOpcional xs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem primero_primeroOpcional: forall (xs:ListaNat) (d:nat),&lt;br /&gt;
  primero d xs = eliminaOpcionalNat d (primeroOpcional xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs d.             (* xs : ListaNat&lt;br /&gt;
                              d : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              primero d xs = eliminaOpcionalNat d (primeroOpcional xs) *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* d : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              primero d [] = eliminaOpcionalNat d (primeroOpcional []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* x : nat&lt;br /&gt;
                              xs&amp;#039; : ListaNat&lt;br /&gt;
                              d : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              primero d (x :: xs&amp;#039;) = &lt;br /&gt;
                              eliminaOpcionalNat d (primeroOpcional (x :: xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                 (* x = x *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Finalizar el módulo ListaNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Diccionarios (o funciones parciales)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Definir el tipo id (por identificador) con el&lt;br /&gt;
   constructor &lt;br /&gt;
      Id : nat -&amp;gt; id.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Definir la función&lt;br /&gt;
      iguales_id : id -&amp;gt; id -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_id x1 x2) se verifica si tienen la misma clave. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      iguales_id (Id 3) (Id 3) = true : bool&lt;br /&gt;
      iguales_id (Id 3) (Id 4) = false : bool&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition iguales_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; iguales_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (iguales_id (Id 3) (Id 3)).&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
Compute (iguales_id (Id 3) (Id 4)).&lt;br /&gt;
(* ===&amp;gt; false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que iguales_id es reflexiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_refl : forall x:id, iguales_id x x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro x.                  (* x : id&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id x x = true *)&lt;br /&gt;
  destruct x.               (* iguales_id (Id n) (Id n) = true *)&lt;br /&gt;
  simpl.                    (* iguales_nat n n = true *)&lt;br /&gt;
  rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Iniciar el módulo Diccionario que importa a ListaNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Diccionario.&lt;br /&gt;
Export ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.4. Definir el tipo diccionario con los contructores&lt;br /&gt;
      vacio    : diccionario&lt;br /&gt;
      registro : id -&amp;gt; nat -&amp;gt; diccionario -&amp;gt; diccionario.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive diccionario : Type :=&lt;br /&gt;
  | vacio    : diccionario&lt;br /&gt;
  | registro : id -&amp;gt; nat -&amp;gt; diccionario -&amp;gt; diccionario.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.5. Definir los diccionarios cuyos elementos son&lt;br /&gt;
      + []&lt;br /&gt;
      + [(3,6)]&lt;br /&gt;
      + [(2,4), (3,6)]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition diccionario1 := vacio.&lt;br /&gt;
Definition diccionario2 := registro (Id 3) 6 diccionario1.&lt;br /&gt;
Definition diccionario3 := registro (Id 2) 4 diccionario2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.6. Definir la función&lt;br /&gt;
      valor : id -&amp;gt; diccionario -&amp;gt; OpcionalNat &lt;br /&gt;
   tal que (valor i d) es el valor de la entrada de d con clave i, o&lt;br /&gt;
   None si d no tiene ninguna entrada con clave i. Por ejemplo,&lt;br /&gt;
      valor (Id 2) diccionario3 = Some 4&lt;br /&gt;
      valor (Id 2) diccionario2 = None&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint valor (x : id) (d : diccionario) : OpcionalNat :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | vacio           =&amp;gt; None&lt;br /&gt;
  | registro y v d&amp;#039; =&amp;gt; if iguales_id x y&lt;br /&gt;
                      then Some v&lt;br /&gt;
                      else valor x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (valor (Id 2) diccionario3).&lt;br /&gt;
(* = Some 4 : OpcionalNat *)&lt;br /&gt;
Compute (valor (Id 2) diccionario2).&lt;br /&gt;
(* = None : OpcionalNat*)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.7. Definir la función&lt;br /&gt;
      actualiza : diccionario -&amp;gt; id -&amp;gt; nat -&amp;gt; diccionario&lt;br /&gt;
   tal que (actualiza d x v) es el diccionario obtenido a partir del d&lt;br /&gt;
   + si d tiene un elemento con clave x, le cambia su valor a v&lt;br /&gt;
   + en caso contrario, le añade el elemento v con clave x &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition actualiza (d : diccionario)&lt;br /&gt;
                     (x : id) (v : nat)&lt;br /&gt;
                     : diccionario :=&lt;br /&gt;
  registro x v d.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar que&lt;br /&gt;
      forall (d : diccionario) (x : id) (v: nat),&lt;br /&gt;
        valor x (actualiza d x v) = Some v.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem valor_actualiza: forall (d : diccionario) (x : id) (v: nat),&lt;br /&gt;
    valor x (actualiza d x v) = Some v.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros d x v.             (* d : diccionario&lt;br /&gt;
                               x : id&lt;br /&gt;
                               v : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               valor x (actualiza d x v) = Some v *)&lt;br /&gt;
  destruct x.               (* valor (Id n) (actualiza d (Id n) v) = Some v *)&lt;br /&gt;
  simpl.                    (* (if iguales_nat n n then Some v &lt;br /&gt;
                                                   else valor (Id n) d) &lt;br /&gt;
                               = Some v *)&lt;br /&gt;
  rewrite iguales_nat_refl. (* Some v = Some v *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3. Demostrar que&lt;br /&gt;
      forall (d : diccionario) (x y : id) (o: nat),&lt;br /&gt;
        iguales_id x y = false -&amp;gt; valor x (actualiza d y o) = valor x d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem actualiza_neq :&lt;br /&gt;
  forall (d : diccionario) (x y : id) (o: nat),&lt;br /&gt;
    iguales_id x y = false -&amp;gt; valor x (actualiza d y o) = valor x d.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros d x y o p. (* d : diccionario&lt;br /&gt;
                       x, y : id&lt;br /&gt;
                       o : nat&lt;br /&gt;
                       p : iguales_id x y = false&lt;br /&gt;
                       ============================&lt;br /&gt;
                       valor x (actualiza d y o) = valor x d *)&lt;br /&gt;
  simpl.            (* (if iguales_id x y then Some o &lt;br /&gt;
                                          else valor x d) &lt;br /&gt;
                       = valor x d *)&lt;br /&gt;
  rewrite p.        (* valor x d = valor x d *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.8. Finalizar el módulo Diccionario&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Diccionario.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Lists.html Lists (working with structured data)] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T3_Listas.v&amp;diff=58</id>
		<title>Archivo:T3 Listas.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T3_Listas.v&amp;diff=58"/>
		<updated>2018-08-03T10:47:35Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_3:_Datos_estructurados_en_Coq&amp;diff=57</id>
		<title>Tema 3: Datos estructurados en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_3:_Datos_estructurados_en_Coq&amp;diff=57"/>
		<updated>2018-08-03T10:46:46Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página creada con «En este tema se introduce mediante ejemplos cómo definir tipos de datos estructurados (como pares, listas, opcionales y diccionarios), definir funciones con los tipos defi…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos cómo definir tipos de datos estructurados (como pares, listas, opcionales y diccionarios), definir funciones con los tipos definidos y demostrar propiedades de dichas dunciones. &lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T3_Listas.v|T3_Listas.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T3: Datos estructurados en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T2_Induccion.&lt;br /&gt;
&lt;br /&gt;
(* El contenido de la teoría es&lt;br /&gt;
   1. Pares de números &lt;br /&gt;
   2. Listas de números &lt;br /&gt;
      1. El tipo de la lista de números. &lt;br /&gt;
      2. La función repite (repeat)  &lt;br /&gt;
      3. La función longitud (length)  &lt;br /&gt;
      4. La función conc (app)  &lt;br /&gt;
      5. Las funciones primero (hd) y resto (tl)&lt;br /&gt;
      6. Ejercicios sobre listas de números &lt;br /&gt;
      7. Multiconjuntos como listas &lt;br /&gt;
   3. Razonamiento sobre listas&lt;br /&gt;
      1. Demostraciones por simplificación &lt;br /&gt;
      2. Demostraciones por casos &lt;br /&gt;
      3. Demostraciones por inducción&lt;br /&gt;
      4. Ejercicios &lt;br /&gt;
   4. Opcionales&lt;br /&gt;
   5. Diccionarios (o funciones parciales)&lt;br /&gt;
   6. Bibliografía&lt;br /&gt;
*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Pares de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Se iniciar el módulo ListaNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module ListaNat. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Definir el tipo ProdNat para los pares de números&lt;br /&gt;
   naturales con el constructor&lt;br /&gt;
      par : nat -&amp;gt; nat -&amp;gt; ProdNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive ProdNat : Type :=&lt;br /&gt;
  par : nat -&amp;gt; nat -&amp;gt; ProdNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Calcular el tipo de la expresión (par 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (par 3 5).&lt;br /&gt;
(* ===&amp;gt; par 3 5 : ProdNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3. Definir la función&lt;br /&gt;
      fst : ProdNat -&amp;gt; nat&lt;br /&gt;
   tal que (fst p) es la primera componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | par x y =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4. Evaluar la expresión &lt;br /&gt;
      fst (par 3 5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (fst (par 3 5)).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5. Definir la función&lt;br /&gt;
      snd : ProdNat -&amp;gt; nat&lt;br /&gt;
   tal que (snd p) es la segunda componente de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | par x y =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6. Definir la notación (x,y) como una abreviaura de &lt;br /&gt;
   (par x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (par x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.7. Evaluar la expresión &lt;br /&gt;
      fst (3,5)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (fst (3,5)).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.8. Redefinir la función fst usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fst&amp;#039; (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.9. Redefinir la función snd usando la abreviatura de pares.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition snd&amp;#039; (p : ProdNat) : nat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.10. Definir la función&lt;br /&gt;
      intercambia : ProdNat -&amp;gt; ProdNat&lt;br /&gt;
   tal que (intercambia p) es el par obtenido intercambiando las&lt;br /&gt;
   componentes de p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition intercambia (p : ProdNat) : ProdNat := &lt;br /&gt;
  match p with&lt;br /&gt;
  | (x,y) =&amp;gt; (y,x)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.11. Demostrar que para todos los naturales&lt;br /&gt;
      (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem par_componentes1 : forall (n m : nat),&lt;br /&gt;
  (n,m) = (fst (n,m), snd (n,m)).&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.12. Demostrar que para todo par de naturales&lt;br /&gt;
      p = (fst p, snd p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem par_componentes2 : forall (p : ProdNat),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl. (* &lt;br /&gt;
            ============================&lt;br /&gt;
            forall p : ProdNat, p = (fst p, snd p) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem par_componentes : forall (p : ProdNat),&lt;br /&gt;
  p = (fst p, snd p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros p.            (* p : ProdNat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          p = (fst p, snd p) *)&lt;br /&gt;
  destruct p as [n m]. (* n, m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          (n, m) = (fst (n, m), snd (n, m)) *)&lt;br /&gt;
  simpl.               (* (n, m) = (n, m) *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar que para todo par de naturales p,&lt;br /&gt;
      (snd p, fst p) = intercambia p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ejercicio_1_1: forall p : ProdNat,&lt;br /&gt;
  (snd p, fst p) = intercambia p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro p.             (* p : ProdNat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          (snd p, fst p) = intercambia p *)&lt;br /&gt;
  destruct p as [n m]. (* n, m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          (snd (n, m), fst (n, m)) = intercambia (n, m) *)&lt;br /&gt;
  simpl.               (* (m, n) = (m, n) *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar que para todo par de naturales p,&lt;br /&gt;
      fst (intercambia p) = snd p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem ejercicio_1_2: forall p : ProdNat,&lt;br /&gt;
  fst (intercambia p) = snd p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro p.             (* p : ProdNat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          fst (intercambia p) = snd p *)&lt;br /&gt;
  destruct p as [n m]. (* n, m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                          fst (intercambia (n, m)) = snd (n, m) *)&lt;br /&gt;
  simpl.               (* m = m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.1. El tipo de la lista de números. &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Definir el tipo ListaNat de la lista de los números&lt;br /&gt;
   naturales y cuyo constructores son &lt;br /&gt;
   + nil (la lista vacía) y &lt;br /&gt;
   + cons (tal que (cons x ys) es la lista obtenida añadiéndole x a ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive ListaNat : Type :=&lt;br /&gt;
  | nil  : ListaNat&lt;br /&gt;
  | cons : nat -&amp;gt; ListaNat -&amp;gt; ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Definir la constante &lt;br /&gt;
      ejLista : ListaNat&lt;br /&gt;
   que es la lista cuyos elementos son 1, 2 y 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ejLista := cons 1 (cons 2 (cons 3 nil)).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Definir la notación (x :: ys) como una abreviatura de &lt;br /&gt;
   (cons x ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x :: l&amp;quot; := (cons x l)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.4. Definir la notación de las listas finitas escribiendo&lt;br /&gt;
   sus elementos entre corchetes y separados por puntos y comas.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;[ ]&amp;quot; := nil.&lt;br /&gt;
Notation &amp;quot;[ x ; .. ; y ]&amp;quot; := (cons x .. (cons y nil) ..).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.5. Definir la lista cuyos elementos son 1, 2 y 3 mediante&lt;br /&gt;
   sistintas represerntaciones.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition ejLista1 := 1 :: (2 :: (3 :: nil)).&lt;br /&gt;
Definition ejLista2 := 1 :: 2 :: 3 :: nil.&lt;br /&gt;
Definition ejLista3 := [1;2;3].&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.2. La función repite (repeat)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Definir la función&lt;br /&gt;
      repite : nat -&amp;gt; nat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (repite n k) es la lista formada por k veces el número n. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      repite 5 3 = [5; 5; 5]&lt;br /&gt;
&lt;br /&gt;
   Nota: La función repite es quivalente a la predefinida repeat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repite (n k : nat) : ListaNat :=&lt;br /&gt;
  match k with&lt;br /&gt;
  | O        =&amp;gt; nil&lt;br /&gt;
  | S k&amp;#039; =&amp;gt; n :: (repite n k&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (repite 5 3).&lt;br /&gt;
(* ===&amp;gt; [5; 5; 5] : ListaNat*)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.3. La función longitud (length)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Definir la función&lt;br /&gt;
      longitud : ListaNat -&amp;gt; nat&lt;br /&gt;
   tal que (longitud xs) es el número de elementos de xs. Por ejemplo, &lt;br /&gt;
      longitud [4;2;6] = 3&lt;br /&gt;
&lt;br /&gt;
   Nota: La función longitud es equivalente a la predefinida length&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint longitud (l:ListaNat) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; O&lt;br /&gt;
  | h :: t =&amp;gt; S (longitud t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (longitud [4;2;6]).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.4. La función conc (app)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.1. Definir la función&lt;br /&gt;
      conc : ListaNat -&amp;gt; ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (conc xs ys) es la concatenación de xs e ys. Por ejemplo, &lt;br /&gt;
      conc [1;3] [4;2;3;5] =  [1; 3; 4; 2; 3; 5]&lt;br /&gt;
&lt;br /&gt;
   Nota:La función conc es equivalente a la predefinida app.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint conc (xs ys : ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; ys&lt;br /&gt;
  | x :: zs =&amp;gt; x :: (conc zs ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (conc [1;3] [4;2;3;5]).&lt;br /&gt;
(* ===&amp;gt; [1; 3; 4; 2; 3; 5] : ListaNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.2. Definir la notación (xs ++ ys) como una abreviaura de &lt;br /&gt;
   (conc xs ys).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x ++ y&amp;quot; := (conc x y)&lt;br /&gt;
                     (right associativity, at level 60).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.4.3. Demostrar que&lt;br /&gt;
      [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
      nil     ++ [4;5] = [4;5].&lt;br /&gt;
      [1;2;3] ++ nil   = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_conc1: [1;2;3] ++ [4;5] = [1;2;3;4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_conc2: nil ++ [4;5] = [4;5].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_conc3: [1;2;3] ++ nil = [1;2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.5. Las funciones primero (hd) y resto (tl)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.1. Definir la función&lt;br /&gt;
      primero : nat -&amp;gt; ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (primero d xs) es el primer elemento de xs o d, si xs es la lista&lt;br /&gt;
   vacía. Por ejemplo,&lt;br /&gt;
      primero 7 [3;2;5] = 3 &lt;br /&gt;
      primero 7 []      = 7 &lt;br /&gt;
&lt;br /&gt;
   Nota. La función primero es equivalente a la predefinida hd&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition primero (d : nat) (xs : ListaNat) : nat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil     =&amp;gt; d&lt;br /&gt;
  | y :: ys =&amp;gt; y&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (primero 7 [3;2;5]).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
Compute (primero 7 []).&lt;br /&gt;
(* ===&amp;gt; 7 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.2. Demostrar que &lt;br /&gt;
       primero 0 [1;2;3] = 1.&lt;br /&gt;
       resto [1;2;3]     = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example prop_primero1: primero 0 [1;2;3] = 1.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primero2: primero 0 [] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.3. Definir la función&lt;br /&gt;
      resto : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (resto xs) es el resto de xs. Por ejemplo.&lt;br /&gt;
      resto [3;2;5] = [2; 5]&lt;br /&gt;
      resto []      = [ ]&lt;br /&gt;
&lt;br /&gt;
   Nota. La función resto es equivalente la predefinida tl.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition resto (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil     =&amp;gt; nil&lt;br /&gt;
  | y :: ys =&amp;gt; ys&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (resto [3;2;5]).&lt;br /&gt;
(* ===&amp;gt; [2; 5] : ListaNat *)&lt;br /&gt;
Compute (resto []).&lt;br /&gt;
(* ===&amp;gt; [ ] : ListaNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.5.4. Demostrar que &lt;br /&gt;
       resto [1;2;3] = [2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example prop_resto: resto [1;2;3] = [2;3].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.6. Ejercicios sobre listas de números &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.1. Definir la función&lt;br /&gt;
      noCeros : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (noCeros xs) es la lista de los elementos de xs distintos de&lt;br /&gt;
   cero. Por ejemplo,&lt;br /&gt;
      noCeros [0;1;0;2;3;0;0] = [1;2;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint noCeros (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil =&amp;gt; nil&lt;br /&gt;
  | a::bs =&amp;gt; match a with&lt;br /&gt;
            | 0 =&amp;gt; noCeros bs &lt;br /&gt;
            | _ =&amp;gt;  a :: noCeros bs&lt;br /&gt;
            end&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Compute (noCeros [0;1;0;2;3;0;0]).&lt;br /&gt;
(* ===&amp;gt; [1; 2; 3] : ListaNat  *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.2. Definir la función&lt;br /&gt;
      impares : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (impares xs) es la lista de los elementos impares de&lt;br /&gt;
   xs. Por ejemplo,&lt;br /&gt;
      impares [0;1;0;2;3;0;0] = [1;3].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint impares (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil   =&amp;gt; nil&lt;br /&gt;
  | y::ys =&amp;gt; if esImpar y&lt;br /&gt;
             then y :: impares ys &lt;br /&gt;
             else impares ys&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Compute (impares [0;1;0;2;3;0;0]).&lt;br /&gt;
(* ===&amp;gt; [1; 3] : ListaNat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.3. Definir la función&lt;br /&gt;
      nImpares : ListaNat -&amp;gt; nat&lt;br /&gt;
   tal que (nImpares xs) es el número de elementos impares de xs. Por &lt;br /&gt;
   ejemplo,&lt;br /&gt;
      nImpares [1;0;3;1;4;5] = 4.&lt;br /&gt;
      nImpares [0;2;4]       = 0.&lt;br /&gt;
      nImpares nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nImpares (xs:ListaNat) : nat :=&lt;br /&gt;
  longitud (impares xs). &lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares1: nImpares [1;0;3;1;4;5] = 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares2: nImpares [0;2;4] = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nImpares3: nImpares nil = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.6.4. Definir la función&lt;br /&gt;
      intercaladas : ListaNat -&amp;gt; ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (intercaladas xs ys) es la lista obtenida intercalando los&lt;br /&gt;
   elementos de xs e ys. Por ejemplo,&lt;br /&gt;
      intercaladas [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
      intercaladas [1] [4;5;6]     = [1;4;5;6].&lt;br /&gt;
      intercaladas [1;2;3] [4]     = [1;4;2;3].&lt;br /&gt;
      intercaladas [] [20;30]      = [20;30].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint intercaladas (xs ys : ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; ys&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; match ys with&lt;br /&gt;
              | nil    =&amp;gt; xs&lt;br /&gt;
              | y::ys&amp;#039; =&amp;gt; x::y::intercaladas xs&amp;#039; ys&amp;#039;&lt;br /&gt;
              end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas1: intercaladas [1;2;3] [4;5;6] = [1;4;2;5;3;6].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas2: intercaladas [1] [4;5;6] = [1;4;5;6].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas3: intercaladas [1;2;3] [4] = [1;4;2;3].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_intercaladas4: intercaladas [] [20;30] = [20;30].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 2.7. Multiconjuntos como listas &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.7.1. Un multiconjunto es una colección de elementos donde&lt;br /&gt;
   no importa el orden de los elementos, pero sí el número de&lt;br /&gt;
   ocurrencias de cada elemento.&lt;br /&gt;
&lt;br /&gt;
   Definir el tipo multiconjunto de los multiconjuntos de números&lt;br /&gt;
   naturales. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition multiconjunto := ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.2. Definir la función&lt;br /&gt;
      nOcurrencias : nat -&amp;gt; multiconjunto -&amp;gt; nat &lt;br /&gt;
   tal que (nOcurrencias x ys) es el número de veces que aparece el&lt;br /&gt;
   elemento x en el multiconjunto ys. Por ejemplo,&lt;br /&gt;
      nOcurrencias 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
      nOcurrencias 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nOcurrencias (x:nat) (ys:multiconjunto) : nat :=&lt;br /&gt;
  match ys with&lt;br /&gt;
  | nil    =&amp;gt; 0&lt;br /&gt;
  | y::ys&amp;#039; =&amp;gt; if iguales_nat y x&lt;br /&gt;
              then 1 + nOcurrencias x ys&amp;#039;&lt;br /&gt;
              else nOcurrencias x ys&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_nOcurrencias1: nOcurrencias 1 [1;2;3;1;4;1] = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nOcurrencias2: nOcurrencias 6 [1;2;3;1;4;1] = 0.&lt;br /&gt;
Proof. reflexivity. Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.3. Definir la función&lt;br /&gt;
      suma : multiconjunto -&amp;gt; multiconjunto -&amp;gt; multiconjunto&lt;br /&gt;
   tal que (suma xs ys) es la suma de los multiconjuntos xs e ys. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      suma [1;2;3] [1;4;1]                  = [1; 2; 3; 1; 4; 1]&lt;br /&gt;
      nOcurrencias 1 (suma [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition suma : multiconjunto -&amp;gt; multiconjunto -&amp;gt; multiconjunto :=&lt;br /&gt;
  conc.&lt;br /&gt;
&lt;br /&gt;
Example prop_sum: nOcurrencias 1 (suma [1;2;3] [1;4;1]) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.4. Definir la función&lt;br /&gt;
      agrega : nat -&amp;gt; multiconjunto -&amp;gt; multiconjunto &lt;br /&gt;
   tal que (agrega x ys) es el multiconjunto obtenido añadiendo el&lt;br /&gt;
   elemento x al multiconjunto ys. Por ejemplo,&lt;br /&gt;
      nOcurrencias 1 (agrega 1 [1;4;1]) = 3.&lt;br /&gt;
      nOcurrencias 5 (agrega 1 [1;4;1]) = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition agrega (x:nat) (ys:multiconjunto) : multiconjunto :=&lt;br /&gt;
  x :: ys.&lt;br /&gt;
&lt;br /&gt;
Example prop_agrega1: nOcurrencias 1 (agrega 1 [1;4;1]) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_agrega2: nOcurrencias 5 (agrega 1 [1;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.5. Definir la función&lt;br /&gt;
      pertenece : nat -&amp;gt; multiconjunto -&amp;gt; bool&lt;br /&gt;
   tal que (pertenece x ys) se verfica si x pertenece al multiconjunto&lt;br /&gt;
   ys. Por ejemplo,  &lt;br /&gt;
      pertenece 1 [1;4;1] = true.&lt;br /&gt;
      pertenece 2 [1;4;1] = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pertenece (x:nat) (ys:multiconjunto) : bool := &lt;br /&gt;
  negacion (iguales_nat 0 (nOcurrencias x ys)).&lt;br /&gt;
&lt;br /&gt;
Example prop_pertenece1: pertenece 1 [1;4;1] = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_pertenece2: pertenece 2 [1;4;1] = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.6. Definir la función&lt;br /&gt;
      eliminaUna : nat -&amp;gt; multiconjunto -&amp;gt; multiconjunto&lt;br /&gt;
   tal que (eliminaUna x ys) es el multiconjunto obtenido eliminando una&lt;br /&gt;
   ocurrencia de x en el multiconjunto ys. Por ejemplo, &lt;br /&gt;
      nOcurrencias 5 (eliminaUna 5 [2;1;5;4;1])     = 0.&lt;br /&gt;
      nOcurrencias 4 (eliminaUna 5 [2;1;4;5;1;4])   = 2.&lt;br /&gt;
      nOcurrencias 5 (eliminaUna 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint eliminaUna (x:nat) (ys:multiconjunto) : multiconjunto :=&lt;br /&gt;
  match ys with&lt;br /&gt;
  | nil      =&amp;gt; nil&lt;br /&gt;
  | y :: ys&amp;#039; =&amp;gt; if iguales_nat y x&lt;br /&gt;
               then ys&amp;#039;&lt;br /&gt;
               else y :: eliminaUna x ys&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna1: nOcurrencias 5 (eliminaUna 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna2: nOcurrencias 5 (eliminaUna 5 [2;1;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna3: nOcurrencias 4 (eliminaUna 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaUna4: nOcurrencias 5 (eliminaUna 5 [2;1;5;4;5;1;4]) = 1.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.7. Definir la función&lt;br /&gt;
      eliminaTodas : nat -&amp;gt; multiconjunto -&amp;gt; multiconjunto&lt;br /&gt;
   tal que (eliminaTodas x ys) es el multiconjunto obtenido eliminando&lt;br /&gt;
   todas las ocurrencias de x en el multiconjunto ys. Por ejemplo,&lt;br /&gt;
      nOcurrencias 5 (eliminaTodas 5 [2;1;5;4;1])           = 0.&lt;br /&gt;
      nOcurrencias 5 (eliminaTodas 5 [2;1;4;1])             = 0.&lt;br /&gt;
      nOcurrencias 4 (eliminaTodas 5 [2;1;4;5;1;4])         = 2.&lt;br /&gt;
      nOcurrencias 5 (eliminaTodas 5 [2;1;5;4;5;1;4;5;1;4]) = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint eliminaTodas (x:nat) (ys:multiconjunto) : multiconjunto :=&lt;br /&gt;
  match ys with&lt;br /&gt;
  | nil      =&amp;gt; nil&lt;br /&gt;
  | y :: ys&amp;#039; =&amp;gt; if iguales_nat y x&lt;br /&gt;
               then eliminaTodas x ys&amp;#039;&lt;br /&gt;
               else y :: eliminaTodas x ys&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas1: nOcurrencias 5 (eliminaTodas 5 [2;1;5;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas2: nOcurrencias 5 (eliminaTodas 5 [2;1;4;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas3: nOcurrencias 4 (eliminaTodas 5 [2;1;4;5;1;4]) = 2.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_eliminaTodas4: nOcurrencias 5 (eliminaTodas 5 [1;5;4;5;4;5;1]) = 0.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.8. Definir la función&lt;br /&gt;
      submulticonjunto : multiconjunto -&amp;gt; multiconjunto -&amp;gt; bool&lt;br /&gt;
   tal que (submulticonjunto xs ys) se verifica si xs es un&lt;br /&gt;
   submulticonjunto de ys. Por ejemplo,&lt;br /&gt;
      submulticonjunto [1;2]   [2;1;4;1] = true.&lt;br /&gt;
      submulticonjunto [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint submulticonjunto (xs:multiconjunto) (ys:multiconjunto) : bool :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; pertenece x ys &amp;amp;&amp;amp; submulticonjunto xs&amp;#039; (eliminaUna x ys)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_submulticonjunto1: submulticonjunto [1;2] [2;1;4;1] = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_submulticonjunto2: submulticonjunto [1;2;2] [2;1;4;1] = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.7.9. Escribir una propiedad sobre multiconjuntos con las&lt;br /&gt;
   funciones nOcurrencias y agrega y demostrarla. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nOcurrencias_conc: forall xs ys : multiconjunto, forall n:nat,&lt;br /&gt;
  nOcurrencias n (conc xs ys) = nOcurrencias n xs + nOcurrencias n ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys n.               (* xs, ys : multiconjunto&lt;br /&gt;
                                   n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   nOcurrencias n (xs ++ ys) = &lt;br /&gt;
                                    nOcurrencias n xs + nOcurrencias n ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].&lt;br /&gt;
  -                             (* ys : multiconjunto&lt;br /&gt;
                                   n : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   nOcurrencias n ([ ] ++ ys) = &lt;br /&gt;
                                    nOcurrencias n [ ] + nOcurrencias n ys *)&lt;br /&gt;
    simpl.                      (* nOcurrencias n ys = nOcurrencias n ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039; : ListaNat&lt;br /&gt;
                                   ys : multiconjunto&lt;br /&gt;
                                   n : nat&lt;br /&gt;
                                   HI : nOcurrencias n (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                        nOcurrencias n xs&amp;#039; + nOcurrencias n ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   nOcurrencias n ((x :: xs&amp;#039;) ++ ys) =&lt;br /&gt;
                                    nOcurrencias n (x :: xs&amp;#039;) + &lt;br /&gt;
                                    nOcurrencias n ys *)&lt;br /&gt;
    simpl.                      (* (if iguales_nat x n&lt;br /&gt;
                                    then S (nOcurrencias n (xs&amp;#039; ++ ys))&lt;br /&gt;
                                    else nOcurrencias n (xs&amp;#039; ++ ys)) =&lt;br /&gt;
                                   (if iguales_nat x n &lt;br /&gt;
                                    then S (nOcurrencias n xs&amp;#039;) &lt;br /&gt;
                                    else nOcurrencias n xs&amp;#039;) +&lt;br /&gt;
                                   nOcurrencias n ys  *)&lt;br /&gt;
    destruct (iguales_nat x n). &lt;br /&gt;
    +                           (* S (nOcurrencias n (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                   S (nOcurrencias n xs&amp;#039;) + &lt;br /&gt;
                                   nOcurrencias n ys *)&lt;br /&gt;
      simpl.                    (* S (nOcurrencias n (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                   S (nOcurrencias n xs&amp;#039; + &lt;br /&gt;
                                      nOcurrencias n ys) *)&lt;br /&gt;
      rewrite HI.               (* S (nOcurrencias n xs&amp;#039; + nOcurrencias n ys) =&lt;br /&gt;
                                   S (nOcurrencias n xs&amp;#039; + nOcurrencias n ys) *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                           (* nOcurrencias n (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                   nOcurrencias n xs&amp;#039; + nOcurrencias n ys *)&lt;br /&gt;
      rewrite HI.               (* nOcurrencias n xs&amp;#039; + nOcurrencias n ys =&lt;br /&gt;
                                   nOcurrencias n xs&amp;#039; + nOcurrencias n ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Razonamiento sobre listas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.1.1. Demostrar que, para toda lista de naturales xs,&lt;br /&gt;
      [] ++ xs = xs&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nil_conc : forall xs:ListaNat,&lt;br /&gt;
  [] ++ xs = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.2. Demostraciones por casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.2.1. Demostrar que, para toda lista de naturales xs,&lt;br /&gt;
      pred (longitud xs) = longitud (resto xs)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem resto_longitud_pred : forall xs:ListaNat,&lt;br /&gt;
  pred (longitud xs) = longitud (resto xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.                (* xs : ListaNat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Nat.pred (longitud xs) = longitud (resto xs) *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                         (* &lt;br /&gt;
                               ============================&lt;br /&gt;
                               Nat.pred (longitud []) = longitud (resto []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                         (* x : nat&lt;br /&gt;
                               xs&amp;#039; : ListaNat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               Nat.pred (longitud (x :: xs&amp;#039;)) = &lt;br /&gt;
                                longitud (resto (x :: xs&amp;#039;)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.3. Demostraciones por inducción&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3.1. Demostrar que la concatenación de listas de naturales&lt;br /&gt;
   es asociativa; es decir,&lt;br /&gt;
      (xs ++ ys) ++ zs = xs ++ (ys ++ zs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_asociativa: forall xs ys zs : ListaNat,&lt;br /&gt;
  (xs ++ ys) ++ zs = xs ++ (ys ++ zs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys zs.             (* xs, ys, zs : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (xs ++ ys) ++ zs = xs ++ (ys ++ zs) *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* ys, zs : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  ([ ] ++ ys) ++ zs = [ ] ++ (ys ++ zs) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039;, ys, zs : ListaNat&lt;br /&gt;
                                  HI : (xs&amp;#039; ++ ys) ++ zs = xs&amp;#039; ++ (ys ++ zs)&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  ((x :: xs&amp;#039;) ++ ys) ++ zs = &lt;br /&gt;
                                   (x :: xs&amp;#039;) ++ (ys ++ zs) *)&lt;br /&gt;
    simpl.                     (* (x :: (xs&amp;#039; ++ ys)) ++ zs = &lt;br /&gt;
                                  x :: (xs&amp;#039; ++ (ys ++ zs)) *)&lt;br /&gt;
    rewrite -&amp;gt; HI.             (* x :: (xs&amp;#039; ++ (ys ++ zs)) = &lt;br /&gt;
                                  x :: (xs&amp;#039; ++ (ys ++ zs)) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3.2. Definir la función&lt;br /&gt;
      inversa : ListaNat -&amp;gt; ListaNat&lt;br /&gt;
   tal que (inversa xs) es la inversa de xs. Por ejemplo,&lt;br /&gt;
      inversa [1;2;3] = [3;2;1].&lt;br /&gt;
      inversa nil     = nil.&lt;br /&gt;
&lt;br /&gt;
   Nota. La función inversa es equivalente a la predefinida rev.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint inversa (xs:ListaNat) : ListaNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; nil&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; inversa xs&amp;#039; ++ [x]&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_inversa1: inversa [1;2;3] = [3;2;1].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_inversa2: inversa nil = nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 3.3.3. Demostrar que&lt;br /&gt;
      longitud (inversa xs) = longitud xs&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem longitud_inversa1: forall xs:ListaNat,&lt;br /&gt;
  longitud (inversa xs) = longitud xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (inversa [ ]) = longitud [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039; : ListaNat&lt;br /&gt;
                                  HI : longitud (inversa xs&amp;#039;) = longitud xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  longitud (inversa (x :: xs&amp;#039;)) = &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* longitud (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                   S (longitud xs&amp;#039;)*)&lt;br /&gt;
    rewrite &amp;lt;- HI.             (* longitud (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                   S (longitud (inversa xs&amp;#039;)) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* Nota: Para simplificar la última expresión se necesita el siguiente lema. *)&lt;br /&gt;
&lt;br /&gt;
Lemma longitud_conc : forall xs ys : ListaNat,&lt;br /&gt;
  longitud (xs ++ ys) = longitud xs + longitud ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys.                 (* xs, ys : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (xs ++ ys) = &lt;br /&gt;
                                    longitud xs + longitud ys *)&lt;br /&gt;
  induction xs as [| x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* ys : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud ([ ] ++ ys) = &lt;br /&gt;
                                    longitud [ ] + longitud ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039;, ys : ListaNat&lt;br /&gt;
                                   HI : longitud (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                         longitud xs&amp;#039; + longitud ys&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                   longitud (x :: xs&amp;#039;) + longitud ys *)&lt;br /&gt;
    simpl.                      (* S (longitud (xs&amp;#039; ++ ys)) = &lt;br /&gt;
                                   S (longitud xs&amp;#039; + longitud ys) *)&lt;br /&gt;
    rewrite -&amp;gt; HI.              (* S (longitud xs&amp;#039; + longitud ys) = &lt;br /&gt;
                                   S (longitud xs&amp;#039; + longitud ys) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem longitud_inversa : forall xs:ListaNat,&lt;br /&gt;
  longitud (inversa xs) = longitud xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.                    (* xs : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (inversa xs) = longitud xs *)&lt;br /&gt;
  induction xs as [| x xs&amp;#039; HI].&lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (inversa [ ]) = longitud [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039; : ListaNat&lt;br /&gt;
                                   HI : longitud (inversa xs&amp;#039;) = longitud xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   longitud (inversa (x :: xs&amp;#039;)) = &lt;br /&gt;
                                    longitud (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* longitud (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                   S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite longitud_conc.      (* longitud (inversa xs&amp;#039;) + longitud [x] = &lt;br /&gt;
                                   S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite HI.                 (* longitud xs&amp;#039; + longitud [x] = &lt;br /&gt;
                                   S (longitud xs&amp;#039;) *)&lt;br /&gt;
    simpl.                      (* longitud xs&amp;#039; + 1 = S (longitud xs&amp;#039;) *)&lt;br /&gt;
    rewrite suma_conmutativa.   (* 1 + longitud xs&amp;#039; = S (longitud xs&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 3.4. Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.1. Demostrar que la lista vacía es el elemento neutro&lt;br /&gt;
   por la derecha de la concatenación de listas. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_nil: forall xs:ListaNat,&lt;br /&gt;
  xs ++ [] = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs.                    (* xs : ListaNat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   xs ++ [ ] = xs *)&lt;br /&gt;
  induction xs as [| x xs&amp;#039; HI]. &lt;br /&gt;
  -                             (* &lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   [ ] ++ [ ] = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* x : nat&lt;br /&gt;
                                   xs&amp;#039; : ListaNat&lt;br /&gt;
                                   HI : xs&amp;#039; ++ [ ] = xs&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (x :: xs&amp;#039;) ++ [ ] = x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                      (* x :: (xs&amp;#039; ++ [ ]) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                 (* x :: xs&amp;#039; = x :: xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.2. Demostrar que inversa es un endomorfismo en &lt;br /&gt;
   (ListaNat,++); es decir,&lt;br /&gt;
      inversa (xs ++ ys) = inversa ys ++ inversa xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_conc: forall xs ys : ListaNat,&lt;br /&gt;
  inversa (xs ++ ys) = inversa ys ++ inversa xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys.                (* xs, ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (xs ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa xs *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa ([ ] ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa [ ] *)&lt;br /&gt;
    simpl.                     (* inversa ys = inversa ys ++ [ ] *)&lt;br /&gt;
    rewrite conc_nil.          (* inversa ys = inversa ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039;, ys : ListaNat&lt;br /&gt;
                                  HI : inversa (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       inversa ys ++ inversa xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  inversa ys ++ inversa (x :: xs&amp;#039;) *)&lt;br /&gt;
    simpl.                     (* inversa (xs&amp;#039; ++ ys) ++ [x] = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    rewrite HI.                (* (inversa ys ++ inversa xs&amp;#039;) ++ [x] = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    rewrite conc_asociativa.   (* inversa ys ++ (inversa xs&amp;#039; ++ [x]) = &lt;br /&gt;
                                  inversa ys ++ (inversa xs&amp;#039; ++ [x]) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.3. Demostrar que inversa es involutiva; es decir,&lt;br /&gt;
      inversa (inversa xs) = xs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_involutiva: forall xs:ListaNat,&lt;br /&gt;
  inversa (inversa xs) = xs.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa [ ]) = [ ] *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039; : ListaNat&lt;br /&gt;
                                  HI : inversa (inversa xs&amp;#039;) = xs&amp;#039;&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  inversa (inversa (x :: xs&amp;#039;)) = x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                     (* inversa (inversa xs&amp;#039; ++ [x]) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite inversa_conc.      (* inversa [x] ++ inversa (inversa xs&amp;#039;) = &lt;br /&gt;
                                  x :: xs&amp;#039; *)&lt;br /&gt;
    simpl.                     (* x :: inversa (inversa xs&amp;#039;) = x :: xs&amp;#039; *)&lt;br /&gt;
    rewrite HI.                (* x :: xs&amp;#039; = x :: xs&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.4. Demostrar que&lt;br /&gt;
      xs ++ (ys ++ (zs ++ vs)) = ((xs ++ ys) ++ zs) ++ vs.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conc_asociativa4 : forall xs ys zs vs : ListaNat,&lt;br /&gt;
  xs ++ (ys ++ (zs ++ vs)) = ((xs ++ ys) ++ zs) ++ vs.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys zs vs.      (* xs, ys, zs, vs : ListaNat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              xs ++ (ys ++ (zs ++ vs)) = &lt;br /&gt;
                              ((xs ++ ys) ++ zs) ++ vs *)&lt;br /&gt;
  rewrite conc_asociativa. (* xs ++ (ys ++ (zs ++ vs)) = &lt;br /&gt;
                              (xs ++ ys) ++ (zs ++ vs) *)&lt;br /&gt;
  rewrite conc_asociativa. (* xs ++ (ys ++ (zs ++ vs)) =&lt;br /&gt;
                              xs ++ (ys ++ (zs ++ vs)) *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.5. Demostrar que al concatenar dos listas no aparecen ni&lt;br /&gt;
   desaparecen ceros. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma noCeros_conc : forall xs ys : ListaNat,&lt;br /&gt;
  noCeros (xs ++ ys) = (noCeros xs) ++ (noCeros ys).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys.                (* xs, ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  noCeros (xs ++ ys) = &lt;br /&gt;
                                  noCeros xs ++ noCeros ys *)&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* ys : ListaNat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  noCeros ([] ++ ys) = &lt;br /&gt;
                                  noCeros [] ++ noCeros ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039;, ys : ListaNat&lt;br /&gt;
                                  HI : noCeros (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                       noCeros xs&amp;#039; ++ noCeros ys&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  noCeros ((x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  noCeros (x :: xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
    destruct x.&lt;br /&gt;
    +                          (* noCeros ((0 :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  noCeros (0 :: xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      simpl.                   (* noCeros (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                  noCeros xs&amp;#039; ++ noCeros ys *)&lt;br /&gt;
      rewrite HI.              (* noCeros xs&amp;#039; ++ noCeros ys = &lt;br /&gt;
                                  noCeros xs&amp;#039; ++ noCeros ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                          (* noCeros ((S x :: xs&amp;#039;) ++ ys) = &lt;br /&gt;
                                  noCeros (S x :: xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      simpl.                   (* S x :: noCeros (xs&amp;#039; ++ ys) = &lt;br /&gt;
                                  (S x :: noCeros xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      rewrite HI.              (* S x :: (noCeros xs&amp;#039; ++ noCeros ys) = &lt;br /&gt;
                                  (S x :: noCeros xs&amp;#039;) ++ noCeros ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.6. Definir la función&lt;br /&gt;
      iguales_lista : ListaNat -&amp;gt; ListaNat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_lista xs ys) se verifica si las listas xs e ys son&lt;br /&gt;
   iguales. Por ejemplo,&lt;br /&gt;
      iguales_lista nil nil         = true.&lt;br /&gt;
      iguales_lista [1;2;3] [1;2;3] = true.&lt;br /&gt;
      iguales_lista [1;2;3] [1;2;4] = false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_lista (xs ys : ListaNat) : bool:=&lt;br /&gt;
  match xs, ys with&lt;br /&gt;
  | nil,    nil    =&amp;gt; true&lt;br /&gt;
  | x::xs&amp;#039;, y::ys&amp;#039; =&amp;gt; iguales_nat x y &amp;amp;&amp;amp; iguales_lista xs&amp;#039; ys&amp;#039;&lt;br /&gt;
  | _, _           =&amp;gt; false&lt;br /&gt;
 end.&lt;br /&gt;
&lt;br /&gt;
Example prop_iguales_lista1: (iguales_lista nil nil = true).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_iguales_lista2: iguales_lista [1;2;3] [1;2;3] = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_iguales_lista3: iguales_lista [1;2;3] [1;2;4] = false.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.7. Demostrar que la igualdad de listas cumple la&lt;br /&gt;
   propiedad reflexiva. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_lista_refl : forall xs:ListaNat,&lt;br /&gt;
  iguales_lista xs xs = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI]. &lt;br /&gt;
  -                            (* &lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  iguales_lista [ ] [ ] = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                            (* x : nat&lt;br /&gt;
                                  xs&amp;#039; : ListaNat&lt;br /&gt;
                                  HI : iguales_lista xs&amp;#039; xs&amp;#039; = true&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  iguales_lista (x :: xs&amp;#039;) (x :: xs&amp;#039;) = true *)&lt;br /&gt;
    simpl.                     (* iguales_nat x x &amp;amp;&amp;amp; &lt;br /&gt;
                                  iguales_lista xs&amp;#039; xs&amp;#039; = true *)&lt;br /&gt;
    rewrite HI.                (* iguales_nat x x &amp;amp;&amp;amp; true = true *)&lt;br /&gt;
    rewrite iguales_nat_refl.  (* true &amp;amp;&amp;amp; true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.8. Demostrar que al incluir un elemento en un&lt;br /&gt;
   multiconjunto, ese elemento aparece al menos una vez en el&lt;br /&gt;
   resultado. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nOcurrencias_agrega: forall (x:nat) (xs:multiconjunto),&lt;br /&gt;
  menor_o_igual 1 (nOcurrencias x (agrega x xs)) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x xs.              (* x : nat&lt;br /&gt;
                               xs : multiconjunto&lt;br /&gt;
                               ============================&lt;br /&gt;
                               menor_o_igual 1 (nOcurrencias x (agrega x xs)) =&lt;br /&gt;
                               true *)&lt;br /&gt;
  simpl.                    (* match&lt;br /&gt;
                                (if iguales_nat x x then S (nOcurrencias x xs) &lt;br /&gt;
                                                    else nOcurrencias x xs)&lt;br /&gt;
                                with&lt;br /&gt;
                                | 0 =&amp;gt; false&lt;br /&gt;
                                | S _ =&amp;gt; true&lt;br /&gt;
                                end = &lt;br /&gt;
                               true *)&lt;br /&gt;
  rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.9. Demostrar que cada número natural es menor o igual&lt;br /&gt;
   que su siguiente. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_n_Sn: forall n:nat,&lt;br /&gt;
  menor_o_igual n (S n) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                (* n : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              menor_o_igual n (S n) = true *)&lt;br /&gt;
  induction n as [|n&amp;#039; HI]. &lt;br /&gt;
  -                        (* &lt;br /&gt;
                              ============================&lt;br /&gt;
                              menor_o_igual 0 1 = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* n&amp;#039; : nat&lt;br /&gt;
                              HI : menor_o_igual n&amp;#039; (S n&amp;#039;) = true&lt;br /&gt;
                              ============================&lt;br /&gt;
                              menor_o_igual (S n&amp;#039;) (S (S n&amp;#039;)) = true *)&lt;br /&gt;
    simpl.                 (* menor_o_igual n&amp;#039; (S n&amp;#039;) = true *)&lt;br /&gt;
    rewrite HI.            (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.10. Demostrar que al borrar una ocurrencia de 0 de un&lt;br /&gt;
   multiconjunto el número de ocurrencias de 0 en el resultado es menor&lt;br /&gt;
   o igual que en el original.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem remove_decreases_nOcurrencias: forall (xs : multiconjunto),&lt;br /&gt;
  menor_o_igual (nOcurrencias 0 (eliminaUna 0 xs)) (nOcurrencias 0 xs) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction xs as [|x xs&amp;#039; HI].&lt;br /&gt;
  -                               (* &lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     menor_o_igual (nOcurrencias 0 (eliminaUna 0 [])) &lt;br /&gt;
                                                   (nOcurrencias 0 []) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                               (* x : nat&lt;br /&gt;
                                     xs&amp;#039; : ListaNat&lt;br /&gt;
                                     HI: menor_o_igual (nOcurrencias 0 (eliminaUna 0 xs&amp;#039;))&lt;br /&gt;
                                                        (nOcurrencias 0 xs&amp;#039;) &lt;br /&gt;
                                         = true &lt;br /&gt;
                                     ============================&lt;br /&gt;
                                     menor_o_igual (nOcurrencias 0 (eliminaUna 0 (x::xs&amp;#039;)))&lt;br /&gt;
                                                    (nOcurrencias 0 (x :: xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
    destruct x.&lt;br /&gt;
    +                             (* menor_o_igual (nOcurrencias 0 (eliminaUna 0 (0::xs&amp;#039;)))&lt;br /&gt;
                                                   (nOcurrencias 0 (0 :: xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      simpl.                      (* menor_o_igual (nOcurrencias 0 xs&amp;#039;) &lt;br /&gt;
                                                   (S (nOcurrencias 0 xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      rewrite menor_o_igual_n_Sn. (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                             (* menor_o_igual (nOcurrencias 0 &lt;br /&gt;
                                                     (eliminaUna 0 (S x :: xs&amp;#039;)))&lt;br /&gt;
                                                   (nOcurrencias 0 (S x :: xs&amp;#039;)) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      simpl.                      (* menor_o_igual (nOcurrencias 0 (eliminaUna 0 xs&amp;#039;)) &lt;br /&gt;
                                                   (nOcurrencias 0 xs&amp;#039;) &lt;br /&gt;
                                     = true *)&lt;br /&gt;
      rewrite HI.                 (* true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.    &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.11. Escribir un teorema con las funciones nOcurrencias&lt;br /&gt;
   y suma de los multiconjuntos. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem nOcurrencias_suma:&lt;br /&gt;
  forall x : nat, forall xs ys : multiconjunto,&lt;br /&gt;
   nOcurrencias x (suma xs ys) = nOcurrencias x xs + nOcurrencias x ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros x xs ys.                (* x : nat&lt;br /&gt;
                                    xs, ys : multiconjunto&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    nOcurrencias x (suma xs ys) = &lt;br /&gt;
                                    nOcurrencias x xs + nOcurrencias x ys *)&lt;br /&gt;
  induction xs as [|x&amp;#039; xs&amp;#039; HI].&lt;br /&gt;
  -                              (* x : nat&lt;br /&gt;
                                    ys : multiconjunto&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    nOcurrencias x (suma [ ] ys) = &lt;br /&gt;
                                    nOcurrencias x [ ] + nOcurrencias x ys *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* x, x&amp;#039; : nat&lt;br /&gt;
                                    xs&amp;#039; : ListaNat&lt;br /&gt;
                                    ys : multiconjunto&lt;br /&gt;
                                    HI : nOcurrencias x (suma xs&amp;#039; ys) = &lt;br /&gt;
                                         nOcurrencias x xs&amp;#039; + nOcurrencias x ys&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    nOcurrencias x (suma (x&amp;#039; :: xs&amp;#039;) ys) = &lt;br /&gt;
                                    nOcurrencias x (x&amp;#039; :: xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
    simpl.                       (* (if iguales_nat x&amp;#039; x&lt;br /&gt;
                                        then S (nOcurrencias x (suma xs&amp;#039; ys))&lt;br /&gt;
                                        else nOcurrencias x (suma xs&amp;#039; ys)) &lt;br /&gt;
                                    =&lt;br /&gt;
                                    (if iguales_nat x&amp;#039; x &lt;br /&gt;
                                        then S (nOcurrencias x xs&amp;#039;) &lt;br /&gt;
                                        else nOcurrencias x xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
    destruct (iguales_nat x&amp;#039; x). &lt;br /&gt;
    +                            (* S (nOcurrencias x (suma xs&amp;#039; ys)) = &lt;br /&gt;
                                    S (nOcurrencias x xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
      rewrite HI.                (* S (nOcurrencias x xs&amp;#039; + nOcurrencias x ys) = &lt;br /&gt;
                                    S (nOcurrencias x xs&amp;#039;) + nOcurrencias x ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +                            (* nOcurrencias x (suma xs&amp;#039; ys) = &lt;br /&gt;
                                    nOcurrencias x xs&amp;#039; + nOcurrencias x ys *)&lt;br /&gt;
      rewrite HI.                (* nOcurrencias x xs&amp;#039; + nOcurrencias x ys = &lt;br /&gt;
                                    nOcurrencias x xs&amp;#039; + nOcurrencias x ys *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4.12. Demostrar que la función inversa es inyectiva; es&lt;br /&gt;
   decir, &lt;br /&gt;
      forall (xs ys : ListaNat), inversa xs = inversa ys -&amp;gt; xs = ys. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem inversa_inyectiva: forall (xs ys : ListaNat),&lt;br /&gt;
  inversa xs = inversa ys -&amp;gt; xs = ys.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs ys H.                (* xs, ys : ListaNat&lt;br /&gt;
                                    H : inversa xs = inversa ys&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    xs = ys *)&lt;br /&gt;
  rewrite &amp;lt;- inversa_involutiva. (* xs = inversa (inversa ys) *)&lt;br /&gt;
  rewrite &amp;lt;- H.                  (* xs = inversa (inversa xs) *)&lt;br /&gt;
  rewrite inversa_involutiva.    (* xs = xs *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Opcionales&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.1. Definir el tipo OpcionalNat con los contructores&lt;br /&gt;
      Some : nat -&amp;gt; OpcionalNat&lt;br /&gt;
      None : OpcionalNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive OpcionalNat : Type :=&lt;br /&gt;
  | Some : nat -&amp;gt; OpcionalNat&lt;br /&gt;
  | None : OpcionalNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.2. Definir la función&lt;br /&gt;
      nthOpcional : ListaNat -&amp;gt; nat -&amp;gt; OpcionalNat&lt;br /&gt;
   tal que (nthOpcional xs n) es el n-ésimo elemento de la lista xs o None&lt;br /&gt;
   si la lista tiene menos de n elementos. Por ejemplo,&lt;br /&gt;
      nthOpcional [4;5;6;7] 0 = Some 4.&lt;br /&gt;
      nthOpcional [4;5;6;7] 3 = Some 7.&lt;br /&gt;
      nthOpcional [4;5;6;7] 9 = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nthOpcional (xs:ListaNat) (n:nat) : OpcionalNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; None&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; match iguales_nat n O with&lt;br /&gt;
                | true  =&amp;gt; Some x&lt;br /&gt;
                | false =&amp;gt; nthOpcional xs&amp;#039; (pred n)&lt;br /&gt;
                end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional1 : nthOpcional [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional2 : nthOpcional [4;5;6;7] 3 = Some 7.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nthOpcional3 : nthOpcional [4;5;6;7] 9 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* Introduciendo condicionales nos queda: *)&lt;br /&gt;
Fixpoint nthOpcional&amp;#039; (xs:ListaNat) (n:nat) : OpcionalNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil      =&amp;gt; None&lt;br /&gt;
  | x :: xs&amp;#039; =&amp;gt; if iguales_nat x O&lt;br /&gt;
                then Some x&lt;br /&gt;
                else nthOpcional&amp;#039; xs&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 4.3. Definir la función&lt;br /&gt;
      eliminaOpcionalNat -&amp;gt; OpcionalNat -&amp;gt; nat&lt;br /&gt;
   tal que (option_elim d o) es el valor de o, si o tiene valor o es d&lt;br /&gt;
   en caso contrario. Por ejemplo,&lt;br /&gt;
      eliminaOpcionalNat 3 (Some 7) = 7&lt;br /&gt;
      eliminaOpcionalNat 3 None     = 3&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition eliminaOpcionalNat (d : nat) (o : OpcionalNat) : nat :=&lt;br /&gt;
  match o with&lt;br /&gt;
  | Some n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  | None    =&amp;gt; d&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (eliminaOpcionalNat 3 (Some 7)).&lt;br /&gt;
(* ===&amp;gt; 7 : nat *)&lt;br /&gt;
Compute (eliminaOpcionalNat 3 None).&lt;br /&gt;
(* ===&amp;gt; 3 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Definir la función&lt;br /&gt;
      primeroOpcional : ListaNat -&amp;gt; OpcionalNat&lt;br /&gt;
   tal que (primeroOpcional xs) es el primer elemento de xs, si xs es no&lt;br /&gt;
   vacía; o es None, en caso contrario. Por ejemplo,&lt;br /&gt;
      primeroOpcional []    = None.&lt;br /&gt;
      primeroOpcional [1]   = Some 1.&lt;br /&gt;
      primeroOpcional [5;6] = Some 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition primeroOpcional (xs : ListaNat) : OpcionalNat :=&lt;br /&gt;
  match xs with&lt;br /&gt;
  | nil    =&amp;gt; None&lt;br /&gt;
  | x::xs&amp;#039; =&amp;gt; Some x&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional1 : primeroOpcional [] = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional2 : primeroOpcional [1] = Some 1.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_primeroOpcional3 : primeroOpcional [5;6] = Some 5.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.2. Demostrar que&lt;br /&gt;
      primero d xs = eliminaOpcionalNat d (primeroOpcional xs).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem primero_primeroOpcional: forall (xs:ListaNat) (d:nat),&lt;br /&gt;
  primero d xs = eliminaOpcionalNat d (primeroOpcional xs).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros xs d.             (* xs : ListaNat&lt;br /&gt;
                              d : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              primero d xs = eliminaOpcionalNat d (primeroOpcional xs) *)&lt;br /&gt;
  destruct xs as [|x xs&amp;#039;]. &lt;br /&gt;
  -                        (* d : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              primero d [] = eliminaOpcionalNat d (primeroOpcional []) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                        (* x : nat&lt;br /&gt;
                              xs&amp;#039; : ListaNat&lt;br /&gt;
                              d : nat&lt;br /&gt;
                              ============================&lt;br /&gt;
                              primero d (x :: xs&amp;#039;) = &lt;br /&gt;
                              eliminaOpcionalNat d (primeroOpcional (x :: xs&amp;#039;)) *)&lt;br /&gt;
    simpl.                 (* x = x *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Nota. Finalizar el módulo ListaNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 5. Diccionarios (o funciones parciales)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.1. Definir el tipo id (por identificador) con el&lt;br /&gt;
   constructor &lt;br /&gt;
      Id : nat -&amp;gt; id.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive id : Type :=&lt;br /&gt;
  | Id : nat -&amp;gt; id.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.2. Definir la función&lt;br /&gt;
      iguales_id : id -&amp;gt; id -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_id x1 x2) se verifica si tienen la misma clave. Por&lt;br /&gt;
   ejemplo, &lt;br /&gt;
      iguales_id (Id 3) (Id 3) = true : bool&lt;br /&gt;
      iguales_id (Id 3) (Id 4) = false : bool&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition iguales_id (x1 x2 : id) :=&lt;br /&gt;
  match x1, x2 with&lt;br /&gt;
  | Id n1, Id n2 =&amp;gt; iguales_nat n1 n2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (iguales_id (Id 3) (Id 3)).&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
Compute (iguales_id (Id 3) (Id 4)).&lt;br /&gt;
(* ===&amp;gt; false : bool *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.1. Demostrar que iguales_id es reflexiva.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_id_refl : forall x:id, iguales_id x x = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro x.                  (* x : id&lt;br /&gt;
                               ============================&lt;br /&gt;
                               iguales_id x x = true *)&lt;br /&gt;
  destruct x.               (* iguales_id (Id n) (Id n) = true *)&lt;br /&gt;
  simpl.                    (* iguales_nat n n = true *)&lt;br /&gt;
  rewrite iguales_nat_refl. (* true = true *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.3. Iniciar el módulo Diccionario que importa a ListaNat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Diccionario.&lt;br /&gt;
Export ListaNat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.4. Definir el tipo diccionario con los contructores&lt;br /&gt;
      vacio    : diccionario&lt;br /&gt;
      registro : id -&amp;gt; nat -&amp;gt; diccionario -&amp;gt; diccionario.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive diccionario : Type :=&lt;br /&gt;
  | vacio    : diccionario&lt;br /&gt;
  | registro : id -&amp;gt; nat -&amp;gt; diccionario -&amp;gt; diccionario.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.5. Definir los diccionarios cuyos elementos son&lt;br /&gt;
      + []&lt;br /&gt;
      + [(3,6)]&lt;br /&gt;
      + [(2,4), (3,6)]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition diccionario1 := vacio.&lt;br /&gt;
Definition diccionario2 := registro (Id 3) 6 diccionario1.&lt;br /&gt;
Definition diccionario3 := registro (Id 2) 4 diccionario2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.6. Definir la función&lt;br /&gt;
      valor : id -&amp;gt; diccionario -&amp;gt; OpcionalNat &lt;br /&gt;
   tal que (valor i d) es el valor de la entrada de d con clave i, o&lt;br /&gt;
   None si d no tiene ninguna entrada con clave i. Por ejemplo,&lt;br /&gt;
      valor (Id 2) diccionario3 = Some 4&lt;br /&gt;
      valor (Id 2) diccionario2 = None&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint valor (x : id) (d : diccionario) : OpcionalNat :=&lt;br /&gt;
  match d with&lt;br /&gt;
  | vacio           =&amp;gt; None&lt;br /&gt;
  | registro y v d&amp;#039; =&amp;gt; if iguales_id x y&lt;br /&gt;
                      then Some v&lt;br /&gt;
                      else valor x d&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (valor (Id 2) diccionario3).&lt;br /&gt;
(* = Some 4 : OpcionalNat *)&lt;br /&gt;
Compute (valor (Id 2) diccionario2).&lt;br /&gt;
(* = None : OpcionalNat*)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.7. Definir la función&lt;br /&gt;
      actualiza : diccionario -&amp;gt; id -&amp;gt; nat -&amp;gt; diccionario&lt;br /&gt;
   tal que (actualiza d x v) es el diccionario obtenido a partir del d&lt;br /&gt;
   + si d tiene un elemento con clave x, le cambia su valor a v&lt;br /&gt;
   + en caso contrario, le añade el elemento v con clave x &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition actualiza (d : diccionario)&lt;br /&gt;
                     (x : id) (v : nat)&lt;br /&gt;
                     : diccionario :=&lt;br /&gt;
  registro x v d.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.2. Demostrar que&lt;br /&gt;
      forall (d : diccionario) (x : id) (v: nat),&lt;br /&gt;
        valor x (actualiza d x v) = Some v.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem valor_actualiza: forall (d : diccionario) (x : id) (v: nat),&lt;br /&gt;
    valor x (actualiza d x v) = Some v.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros d x v.             (* d : diccionario&lt;br /&gt;
                               x : id&lt;br /&gt;
                               v : nat&lt;br /&gt;
                               ============================&lt;br /&gt;
                               valor x (actualiza d x v) = Some v *)&lt;br /&gt;
  destruct x.               (* valor (Id n) (actualiza d (Id n) v) = Some v *)&lt;br /&gt;
  simpl.                    (* (if iguales_nat n n then Some v &lt;br /&gt;
                                                   else valor (Id n) d) &lt;br /&gt;
                               = Some v *)&lt;br /&gt;
  rewrite iguales_nat_refl. (* Some v = Some v *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 5.3. Demostrar que&lt;br /&gt;
      forall (d : diccionario) (x y : id) (o: nat),&lt;br /&gt;
        iguales_id x y = false -&amp;gt; valor x (actualiza d y o) = valor x d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem actualiza_neq :&lt;br /&gt;
  forall (d : diccionario) (x y : id) (o: nat),&lt;br /&gt;
    iguales_id x y = false -&amp;gt; valor x (actualiza d y o) = valor x d.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros d x y o p. (* d : diccionario&lt;br /&gt;
                       x, y : id&lt;br /&gt;
                       o : nat&lt;br /&gt;
                       p : iguales_id x y = false&lt;br /&gt;
                       ============================&lt;br /&gt;
                       valor x (actualiza d y o) = valor x d *)&lt;br /&gt;
  simpl.            (* (if iguales_id x y then Some o &lt;br /&gt;
                                          else valor x d) &lt;br /&gt;
                       = valor x d *)&lt;br /&gt;
  rewrite p.        (* valor x d = valor x d *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 5.8. Finalizar el módulo Diccionario&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Diccionario.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [https://softwarefoundations.cis.upenn.edu/current/lf-current/Lists.html Lists (working with structured data)] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=56</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=56"/>
		<updated>2018-08-03T10:46:02Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=55</id>
		<title>Página principal</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=55"/>
		<updated>2018-08-03T10:45:41Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;br /&gt;
* [[Tema 3: Datos estructurados en Coq]].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=53</id>
		<title>MediaWiki:Mainpage</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=53"/>
		<updated>2018-08-03T10:42:18Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Jalonso trasladó la página MediaWiki:Demostración Asistida por Ordenador con Coq a MediaWiki:Mainpage: revertir&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Demostración Asistida por Ordenador con Coq&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=54</id>
		<title>MediaWiki:Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=54"/>
		<updated>2018-08-03T10:42:18Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Jalonso trasladó la página MediaWiki:Demostración Asistida por Ordenador con Coq a MediaWiki:Mainpage: revertir&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECCIÓN [[MediaWiki:Mainpage]]&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=52</id>
		<title>MediaWiki:Mainpage</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=52"/>
		<updated>2018-08-03T10:40:56Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Jalonso trasladó la página MediaWiki:Mainpage a MediaWiki:Demostración Asistida por Ordenador con Coq sin dejar una redirección&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Demostración Asistida por Ordenador con Coq&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T1_PF_en_Coq.v&amp;diff=51</id>
		<title>Archivo:T1 PF en Coq.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T1_PF_en_Coq.v&amp;diff=51"/>
		<updated>2018-07-31T13:07:16Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Jalonso subió una nueva versión de Archivo:T1 PF en Coq.v&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T2_Induccion.v&amp;diff=50</id>
		<title>Archivo:T2 Induccion.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T2_Induccion.v&amp;diff=50"/>
		<updated>2018-07-31T13:06:51Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=49</id>
		<title>Tema 2: Demostraciones por inducción sobre los números naturales en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=49"/>
		<updated>2018-07-31T13:06:35Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: /* Teoría */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos cómo demostrar en Coq propiedades de funciones definidas sobre los números naturales. El principal método de demostración que se utiliza es el de inducción.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T2_Induccion.v|T2_Induccion.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T2: Demostraciones por inducción sobre los números naturales en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T1_PF_en_Coq.&lt;br /&gt;
&lt;br /&gt;
(* El contenido de la teoría es&lt;br /&gt;
1. Demostraciones por inducción. &lt;br /&gt;
2. Demostraciones anidadas.&lt;br /&gt;
3. Demostraciones formales vs demostraciones informales.&lt;br /&gt;
4. Ejercicios complementarios *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Demostraciones por inducción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n = n + 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento: con métodos elementales *)&lt;br /&gt;
Theorem suma_n_0_a: forall n:nat, n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento: con casos *)&lt;br /&gt;
Theorem suma_n_0_b : forall n:nat,&lt;br /&gt;
  n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            n = n + 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                            0 = 0 + 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S n&amp;#039; + 0  *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 3ª intento: con inducción *)&lt;br /&gt;
Theorem suma_n_0 : forall n:nat,&lt;br /&gt;
    n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = n + 0 *) &lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*   &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; = n&amp;#039; + 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; = S n&amp;#039; + 0 *)&lt;br /&gt;
    simpl.                    (* S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.          (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que&lt;br /&gt;
      forall n, n - n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem resta_n_n: forall n, n - n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n - n = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*  &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 - 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; - n&amp;#039; = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; - S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.                    (* n&amp;#039; - n&amp;#039; = 0 *)&lt;br /&gt;
    rewrite -&amp;gt; IHn&amp;#039;.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n * 0 = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem multiplica_n_0: forall n:nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * 0 = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * 0 = 0 *)&lt;br /&gt;
    reflexivity.      &lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; * 0 = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * 0 = 0 *)   &lt;br /&gt;
    simpl.                    (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    rewrite IHn&amp;#039;.             (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar que, &lt;br /&gt;
      forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_Sm: forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                (*  n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S (n + m) = n + S m *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S (0 + m) = 0 + S m *)&lt;br /&gt;
    simpl.                   (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S m = S m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* S (S n&amp;#039; + m) = S n&amp;#039; + S m *)&lt;br /&gt;
    simpl.                   (* S (S (n&amp;#039; + m)) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (n&amp;#039; + S m) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.3. Demostrar que &lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_conmutativa: forall n m : nat,&lt;br /&gt;
  n + m = m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros  n m.               (* n, m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + m = m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + m = m + 0 *)&lt;br /&gt;
    simpl.                   (* m = m + 0 *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_0.     (* m = m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + m = m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + m) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (m + n&amp;#039;) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_Sm.    (* S (m + n&amp;#039;) = S (m + n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.4. Demostrar que &lt;br /&gt;
      forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_asociativa: forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + (m + p) = (n + m) + p *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + (m + p) = (0 + m) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + (m + p) = n&amp;#039; + m + p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + (m + p) = (S n&amp;#039; + m) + p *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.5. Se considera la siguiente función que dobla su argumento. &lt;br /&gt;
      Fixpoint doble (n:nat) :=&lt;br /&gt;
        match n with&lt;br /&gt;
        | O    =&amp;gt; O&lt;br /&gt;
        | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall n, doble n = n + n. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint doble (n:nat) :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; O&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Lemma doble_suma : forall n, doble n = n + n .&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble n = n + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : doble n&amp;#039; = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble (S n&amp;#039;) = S n&amp;#039; + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (S (doble n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (S (n&amp;#039; + n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite suma_n_Sm.       (* S (n&amp;#039; + S n&amp;#039;) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6. Demostrar que&lt;br /&gt;
      forall n : nat, esPar (S n) = negacion (esPar n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_S : forall n : nat,&lt;br /&gt;
  esPar (S n) = negacion (esPar n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S n) = negacion (esPar n) *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar 1 = negacion (esPar 0) *)&lt;br /&gt;
    simpl.                       (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                              (* n&amp;#039; : nat&lt;br /&gt;
                                    IHn&amp;#039; : esPar (S n&amp;#039;) = negacion (esPar n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (esPar (S n&amp;#039;)) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.                (* esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (negacion (esPar n&amp;#039;)) *)&lt;br /&gt;
    rewrite negacion_involutiva. (* esPar (S (S n&amp;#039;)) = esPar n&amp;#039; *)&lt;br /&gt;
    simpl.                       (* esPar n&amp;#039; = esPar n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Demostraciones anidadas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_suma&amp;#039;: forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.            (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
  assert (H: 0 + n = n). &lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 + n = n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            H : 0 + n = n&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
    rewrite -&amp;gt; H.        (* n * m = n * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall n m p q : nat, (n + m) + (p + q) = (m + n) + (p + q)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento sin assert*)&lt;br /&gt;
Theorem suma_reordenada_1: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.              (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  rewrite -&amp;gt; suma_conmutativa. (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  p + q + (n + m) = m + n + (p + q) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento con assert *)&lt;br /&gt;
Theorem suma_reordenada: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.                (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  assert (H: n + m = m + n).&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    n + m = m + n *)&lt;br /&gt;
    rewrite -&amp;gt; suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    H : n + m = m + n&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
    rewrite -&amp;gt; H.                (* m + n + (p + q) = m + n + (p + q) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Demostraciones formales vs demostraciones informales&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + (m + p) = (0 + m) + p.&lt;br /&gt;
     Esto es consecuencia inmediata de la definición de suma.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + (m + p) = (n&amp;#039; + m) + p.                 &lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        (S n&amp;#039;) + (m + p) = ((S n&amp;#039;) + m) + p.&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que por la hipótesis de inducción se reduce a&lt;br /&gt;
        S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + m = m + 0&lt;br /&gt;
     que, por la definición de la suma, se reduce a&lt;br /&gt;
        m = m + 0&lt;br /&gt;
     que se verifica por el lema suma_n_0.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        S n&amp;#039; + m = m + S n&amp;#039;&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + m) = m + S n&amp;#039;&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = m + S n&amp;#039;&lt;br /&gt;
     que, por el lema suma_n_Sm, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = S (m + n&amp;#039;)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. Demostrar que&lt;br /&gt;
      forall n:nat, true = iguales_nat n n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_n_n: forall n : nat, true = iguales_nat n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat n n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* true = iguales_nat n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente la demostración del ejercicio anterior.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        true = iguales_nat 0 0&lt;br /&gt;
     que se verifica por la definición de iguales_nat.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) &lt;br /&gt;
     que, por la definición de iguales_nat, se reduce a&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        true = true&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar, usando assert pero no induct,&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada: forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof. &lt;br /&gt;
  intros n m p.               (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m + p = m + n + p *)&lt;br /&gt;
  assert (H : n + m = m + n). &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m = m + n *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 H : n + m = m + n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = (m + n) + p *)&lt;br /&gt;
    rewrite H.                (* (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.2. Demostrar que la multiplicación es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma producto_n_1 : forall n: nat,&lt;br /&gt;
    n * 1 = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n * 1 = n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 * 1 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; * 1 = n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; * 1 = S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; * 1) = S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_1 : forall n : nat,&lt;br /&gt;
    n + 1 = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + 1 = S n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + 1 = 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                HIn&amp;#039; : n&amp;#039; + 1 = S n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + 1 = S (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + 1) = S (S n&amp;#039;) *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* S (S n&amp;#039;) = S (S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_n_Sm: forall n m : nat, &lt;br /&gt;
    n * (m + 1) = n * m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n * (m + 1) = n * m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  -                             (* m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 * (m + 1) = 0 * m + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n&amp;#039;, m : nat&lt;br /&gt;
                                   IHn&amp;#039; : n&amp;#039; * (m + 1) = n&amp;#039; * m + n&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; * (m + 1) = S n&amp;#039; * m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                      (* (m + 1) + n&amp;#039; * (m + 1) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.               (* (m + 1) + (n&amp;#039; * m + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* n&amp;#039; * m + ((m + 1) + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_asociativa. (* n&amp;#039; * m + (m + (1 + n&amp;#039;)) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.        (* n&amp;#039; * m + (m + (n&amp;#039; + 1)) = &lt;br /&gt;
                                   (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_n_1.           (* n&amp;#039; * m + (m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_asociativa.    (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_conmutativa: forall m n : nat,&lt;br /&gt;
  m * n = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * m = m * n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                           (* m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * m = m * 0 *)&lt;br /&gt;
    rewrite multiplica_n_0.   (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039;, m : nat&lt;br /&gt;
                                 HIn&amp;#039; : n&amp;#039; * m = m * n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    simpl.                    (* m + n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* m + m * n&amp;#039; = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.      (* m + m * n&amp;#039; = m * (n&amp;#039; + 1) *)&lt;br /&gt;
    rewrite producto_n_Sm.    (* m + m * n&amp;#039; = m * n&amp;#039; + m *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m * n&amp;#039; + m = m * n&amp;#039; + m *)&lt;br /&gt;
   reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.3. Demostrar que &lt;br /&gt;
      forall n : nat, true = menor_o_igual n n.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_refl: forall n : nat,&lt;br /&gt;
    true = menor_o_igual n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                    (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual n n *)&lt;br /&gt;
  induction n as [| n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039; : nat&lt;br /&gt;
                                 HIn&amp;#039; : true = menor_o_igual n&amp;#039; n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                    (* true = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* menor_o_igual n&amp;#039; n&amp;#039; = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.4. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat 0 (S n) = false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_S: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (S n) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat 0 (S n) = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.5. Demostrar que &lt;br /&gt;
      forall b : bool, conjuncion b false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_false_r : forall b : bool,&lt;br /&gt;
  conjuncion b false = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* b : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                    b &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    true &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    false &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.6. Demostrar que &lt;br /&gt;
      forall n m p : nat, menor_o_igual n m = true -&amp;gt; &lt;br /&gt;
                          menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_suma: forall n m p : nat,&lt;br /&gt;
  menor_o_igual n m = true -&amp;gt; menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H.            (* n, m, p : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (p + n) (p + m) = true *)&lt;br /&gt;
  induction p as [|p&amp;#039; HIp&amp;#039;].&lt;br /&gt;
  -                          (* n, m : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (0 + n) (0 + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual n m = true *)&lt;br /&gt;
    rewrite H.               (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n, m, p&amp;#039; : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                HIp&amp;#039; : menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (S p&amp;#039; + n) (S p&amp;#039; + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true *)&lt;br /&gt;
    rewrite HIp&amp;#039;.            (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.7. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat (S n) 0 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_distinto_0 : forall n:nat,&lt;br /&gt;
  iguales_nat (S n) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.     (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat (S n) 0 = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.8. Demostrar que &lt;br /&gt;
      forall n:nat, 1 * n = n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_1_n: forall n:nat, 1 * n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.          (* n : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       1 * n = n *)&lt;br /&gt;
  simpl.            (* n + 0 = n *)&lt;br /&gt;
  rewrite suma_n_0. (* n + 0 = n + 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.9. Demostrar que &lt;br /&gt;
       forall b c : bool, disyuncion (conjuncion b c)&lt;br /&gt;
                              (disyuncion (negacion b)&lt;br /&gt;
                                          (negacion c))&lt;br /&gt;
                          = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem alternativas: forall b c : bool,&lt;br /&gt;
    disyuncion&lt;br /&gt;
      (conjuncion b c)&lt;br /&gt;
      (disyuncion (negacion b)&lt;br /&gt;
                  (negacion c))&lt;br /&gt;
    = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; true) || (negacion true || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; false) || (negacion true || negacion false) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; true) || (negacion false || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; false) || (negacion false || negacion false)=true *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.10. Demostrar que &lt;br /&gt;
      forall n m p : nat, (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_suma_distributiva_d: forall n m p : nat,&lt;br /&gt;
  (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (n + m) * p = n * p + m * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (0 + m) * p = 0 * p + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                HIn&amp;#039; : (n&amp;#039; + m) * p = n&amp;#039; * p + m * p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (S n&amp;#039; + m) * p = S n&amp;#039; * p + m * p *)&lt;br /&gt;
    simpl.                   (* p + (n&amp;#039; + m) * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* p + (n&amp;#039; * p + m * p) = (p + n&amp;#039;) * p + m * p *)&lt;br /&gt;
    rewrite suma_asociativa. (* (p + n&amp;#039; * p) + m * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.11. Demostrar que &lt;br /&gt;
      forall n m p : nat, n * (m * p) = (n * m) * p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_asociativa: forall n m p : nat,&lt;br /&gt;
  n * (m * p) = (n * m) * p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.     (* n, m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n * (m * p) = (n * m) * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                 (* m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       0 * (m * p) = (0 * m) * p *)&lt;br /&gt;
    simpl.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* n&amp;#039;, m, p : nat&lt;br /&gt;
                       HIn&amp;#039; : n&amp;#039; * (m * p) = (n&amp;#039; * m) * p&lt;br /&gt;
                       ============================&lt;br /&gt;
                       S n&amp;#039; * (m * p) = (S n&amp;#039; * m) * p *)&lt;br /&gt;
    simpl.          (* m * p + n&amp;#039; * (m * p) = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.   (* m * p + (n&amp;#039; * m) * p = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite producto_suma_distributiva_d.&lt;br /&gt;
                    (* m * p + (n&amp;#039; * m) * p = m * p + (n&amp;#039; * m) * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 11. La táctica replace permite especificar el subtérmino&lt;br /&gt;
   que se desea reescribir y su sustituto: &lt;br /&gt;
      replace t with u&lt;br /&gt;
   sustituye todas las copias de la expresión t en el objetivo por la&lt;br /&gt;
   expresión u y añade la ecuación (t = u) como un nuevo subojetivo. &lt;br /&gt;
 &lt;br /&gt;
   El uso de la táctica replace es especialmente útil cuando la táctica &lt;br /&gt;
   rewrite actúa sobre una parte del objetivo que no es la que se desea. &lt;br /&gt;
&lt;br /&gt;
   Demostrar, usando la táctica replace y sin usar &lt;br /&gt;
   [assert (n + m = m + n)], que&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada&amp;#039; : forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.                 (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = (m + n) + p *)&lt;br /&gt;
  replace (n + m) with (m + n). &lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   m + n = n + m *)&lt;br /&gt;
    rewrite suma_conmutativa.   (* n + m = n + m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Teorías: Las teorías se importan con &amp;lt;code&amp;gt;Require Export Nombre&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;assert (H: P)&amp;lt;/code&amp;gt;: Incluyed la demostración de la propiedad P y continúa la demostración añadiendo como premisa la propiedad P con nombre H.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct b&amp;lt;/code&amp;gt;: Distingue dos casos según que b sea True o False.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct n as [| n&amp;#039;]&amp;lt;/code&amp;gt;: Distingue dos casos según que n sea 0 o sea &amp;lt;code&amp;gt;S n&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;induction n as [|n&amp;#039; IHn&amp;#039;]&amp;lt;/code&amp;gt;: Inicia una demostración por inducción sobre n. El caso base en n = 0. El paso de la inducción consiste en suponer la propiedad para n&amp;#039; y demostrarla para S n&amp;#039;. El nombre de la hipótesis de inducción es IHn&amp;#039;. &lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=48</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=48"/>
		<updated>2018-07-31T13:04:44Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* El contenido de la teoría es&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
+ &amp;lt;code&amp;gt;destruct b&amp;lt;/code&amp;gt;: Distingue dos casos según que b sea True o False.&lt;br /&gt;
+ &amp;lt;code&amp;gt;destruct n as [| n&amp;#039;]&amp;lt;/code&amp;gt;: Distingue dos casos según que n sea 0 o sea &amp;lt;code&amp;gt;S n&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=47</id>
		<title>Tema 2: Demostraciones por inducción sobre los números naturales en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=47"/>
		<updated>2018-07-31T13:02:44Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos cómo demostrar en Coq propiedades de funciones definidas sobre los números naturales. El principal método de demostración que se utiliza es el de inducción.&lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T2_Induccion.v|T2Induccion.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T2: Demostraciones por inducción sobre los números naturales en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T1_PF_en_Coq.&lt;br /&gt;
&lt;br /&gt;
(* El contenido de la teoría es&lt;br /&gt;
1. Demostraciones por inducción. &lt;br /&gt;
2. Demostraciones anidadas.&lt;br /&gt;
3. Demostraciones formales vs demostraciones informales.&lt;br /&gt;
4. Ejercicios complementarios *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Demostraciones por inducción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n = n + 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento: con métodos elementales *)&lt;br /&gt;
Theorem suma_n_0_a: forall n:nat, n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento: con casos *)&lt;br /&gt;
Theorem suma_n_0_b : forall n:nat,&lt;br /&gt;
  n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            n = n + 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                            0 = 0 + 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S n&amp;#039; + 0  *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 3ª intento: con inducción *)&lt;br /&gt;
Theorem suma_n_0 : forall n:nat,&lt;br /&gt;
    n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = n + 0 *) &lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*   &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; = n&amp;#039; + 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; = S n&amp;#039; + 0 *)&lt;br /&gt;
    simpl.                    (* S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.          (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que&lt;br /&gt;
      forall n, n - n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem resta_n_n: forall n, n - n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n - n = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*  &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 - 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; - n&amp;#039; = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; - S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.                    (* n&amp;#039; - n&amp;#039; = 0 *)&lt;br /&gt;
    rewrite -&amp;gt; IHn&amp;#039;.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n * 0 = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem multiplica_n_0: forall n:nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * 0 = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * 0 = 0 *)&lt;br /&gt;
    reflexivity.      &lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; * 0 = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * 0 = 0 *)   &lt;br /&gt;
    simpl.                    (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    rewrite IHn&amp;#039;.             (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar que, &lt;br /&gt;
      forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_Sm: forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                (*  n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S (n + m) = n + S m *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S (0 + m) = 0 + S m *)&lt;br /&gt;
    simpl.                   (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S m = S m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* S (S n&amp;#039; + m) = S n&amp;#039; + S m *)&lt;br /&gt;
    simpl.                   (* S (S (n&amp;#039; + m)) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (n&amp;#039; + S m) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.3. Demostrar que &lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_conmutativa: forall n m : nat,&lt;br /&gt;
  n + m = m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros  n m.               (* n, m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + m = m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + m = m + 0 *)&lt;br /&gt;
    simpl.                   (* m = m + 0 *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_0.     (* m = m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + m = m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + m) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (m + n&amp;#039;) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_Sm.    (* S (m + n&amp;#039;) = S (m + n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.4. Demostrar que &lt;br /&gt;
      forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_asociativa: forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + (m + p) = (n + m) + p *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + (m + p) = (0 + m) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + (m + p) = n&amp;#039; + m + p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + (m + p) = (S n&amp;#039; + m) + p *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.5. Se considera la siguiente función que dobla su argumento. &lt;br /&gt;
      Fixpoint doble (n:nat) :=&lt;br /&gt;
        match n with&lt;br /&gt;
        | O    =&amp;gt; O&lt;br /&gt;
        | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall n, doble n = n + n. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint doble (n:nat) :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; O&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Lemma doble_suma : forall n, doble n = n + n .&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble n = n + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : doble n&amp;#039; = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble (S n&amp;#039;) = S n&amp;#039; + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (S (doble n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (S (n&amp;#039; + n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite suma_n_Sm.       (* S (n&amp;#039; + S n&amp;#039;) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6. Demostrar que&lt;br /&gt;
      forall n : nat, esPar (S n) = negacion (esPar n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_S : forall n : nat,&lt;br /&gt;
  esPar (S n) = negacion (esPar n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S n) = negacion (esPar n) *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar 1 = negacion (esPar 0) *)&lt;br /&gt;
    simpl.                       (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                              (* n&amp;#039; : nat&lt;br /&gt;
                                    IHn&amp;#039; : esPar (S n&amp;#039;) = negacion (esPar n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (esPar (S n&amp;#039;)) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.                (* esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (negacion (esPar n&amp;#039;)) *)&lt;br /&gt;
    rewrite negacion_involutiva. (* esPar (S (S n&amp;#039;)) = esPar n&amp;#039; *)&lt;br /&gt;
    simpl.                       (* esPar n&amp;#039; = esPar n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Demostraciones anidadas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_suma&amp;#039;: forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.            (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
  assert (H: 0 + n = n). &lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 + n = n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            H : 0 + n = n&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
    rewrite -&amp;gt; H.        (* n * m = n * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall n m p q : nat, (n + m) + (p + q) = (m + n) + (p + q)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento sin assert*)&lt;br /&gt;
Theorem suma_reordenada_1: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.              (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  rewrite -&amp;gt; suma_conmutativa. (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  p + q + (n + m) = m + n + (p + q) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento con assert *)&lt;br /&gt;
Theorem suma_reordenada: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.                (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  assert (H: n + m = m + n).&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    n + m = m + n *)&lt;br /&gt;
    rewrite -&amp;gt; suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    H : n + m = m + n&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
    rewrite -&amp;gt; H.                (* m + n + (p + q) = m + n + (p + q) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Demostraciones formales vs demostraciones informales&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + (m + p) = (0 + m) + p.&lt;br /&gt;
     Esto es consecuencia inmediata de la definición de suma.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + (m + p) = (n&amp;#039; + m) + p.                 &lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        (S n&amp;#039;) + (m + p) = ((S n&amp;#039;) + m) + p.&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que por la hipótesis de inducción se reduce a&lt;br /&gt;
        S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + m = m + 0&lt;br /&gt;
     que, por la definición de la suma, se reduce a&lt;br /&gt;
        m = m + 0&lt;br /&gt;
     que se verifica por el lema suma_n_0.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        S n&amp;#039; + m = m + S n&amp;#039;&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + m) = m + S n&amp;#039;&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = m + S n&amp;#039;&lt;br /&gt;
     que, por el lema suma_n_Sm, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = S (m + n&amp;#039;)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. Demostrar que&lt;br /&gt;
      forall n:nat, true = iguales_nat n n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_n_n: forall n : nat, true = iguales_nat n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat n n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* true = iguales_nat n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente la demostración del ejercicio anterior.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        true = iguales_nat 0 0&lt;br /&gt;
     que se verifica por la definición de iguales_nat.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) &lt;br /&gt;
     que, por la definición de iguales_nat, se reduce a&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        true = true&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar, usando assert pero no induct,&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada: forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof. &lt;br /&gt;
  intros n m p.               (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m + p = m + n + p *)&lt;br /&gt;
  assert (H : n + m = m + n). &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m = m + n *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 H : n + m = m + n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = (m + n) + p *)&lt;br /&gt;
    rewrite H.                (* (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.2. Demostrar que la multiplicación es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma producto_n_1 : forall n: nat,&lt;br /&gt;
    n * 1 = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n * 1 = n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 * 1 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; * 1 = n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; * 1 = S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; * 1) = S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_1 : forall n : nat,&lt;br /&gt;
    n + 1 = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + 1 = S n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + 1 = 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                HIn&amp;#039; : n&amp;#039; + 1 = S n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + 1 = S (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + 1) = S (S n&amp;#039;) *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* S (S n&amp;#039;) = S (S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_n_Sm: forall n m : nat, &lt;br /&gt;
    n * (m + 1) = n * m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n * (m + 1) = n * m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  -                             (* m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 * (m + 1) = 0 * m + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n&amp;#039;, m : nat&lt;br /&gt;
                                   IHn&amp;#039; : n&amp;#039; * (m + 1) = n&amp;#039; * m + n&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; * (m + 1) = S n&amp;#039; * m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                      (* (m + 1) + n&amp;#039; * (m + 1) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.               (* (m + 1) + (n&amp;#039; * m + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* n&amp;#039; * m + ((m + 1) + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_asociativa. (* n&amp;#039; * m + (m + (1 + n&amp;#039;)) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.        (* n&amp;#039; * m + (m + (n&amp;#039; + 1)) = &lt;br /&gt;
                                   (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_n_1.           (* n&amp;#039; * m + (m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_asociativa.    (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_conmutativa: forall m n : nat,&lt;br /&gt;
  m * n = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * m = m * n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                           (* m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * m = m * 0 *)&lt;br /&gt;
    rewrite multiplica_n_0.   (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039;, m : nat&lt;br /&gt;
                                 HIn&amp;#039; : n&amp;#039; * m = m * n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    simpl.                    (* m + n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* m + m * n&amp;#039; = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.      (* m + m * n&amp;#039; = m * (n&amp;#039; + 1) *)&lt;br /&gt;
    rewrite producto_n_Sm.    (* m + m * n&amp;#039; = m * n&amp;#039; + m *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m * n&amp;#039; + m = m * n&amp;#039; + m *)&lt;br /&gt;
   reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.3. Demostrar que &lt;br /&gt;
      forall n : nat, true = menor_o_igual n n.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_refl: forall n : nat,&lt;br /&gt;
    true = menor_o_igual n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                    (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual n n *)&lt;br /&gt;
  induction n as [| n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039; : nat&lt;br /&gt;
                                 HIn&amp;#039; : true = menor_o_igual n&amp;#039; n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                    (* true = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* menor_o_igual n&amp;#039; n&amp;#039; = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.4. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat 0 (S n) = false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_S: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (S n) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat 0 (S n) = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.5. Demostrar que &lt;br /&gt;
      forall b : bool, conjuncion b false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_false_r : forall b : bool,&lt;br /&gt;
  conjuncion b false = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* b : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                    b &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    true &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    false &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.6. Demostrar que &lt;br /&gt;
      forall n m p : nat, menor_o_igual n m = true -&amp;gt; &lt;br /&gt;
                          menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_suma: forall n m p : nat,&lt;br /&gt;
  menor_o_igual n m = true -&amp;gt; menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H.            (* n, m, p : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (p + n) (p + m) = true *)&lt;br /&gt;
  induction p as [|p&amp;#039; HIp&amp;#039;].&lt;br /&gt;
  -                          (* n, m : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (0 + n) (0 + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual n m = true *)&lt;br /&gt;
    rewrite H.               (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n, m, p&amp;#039; : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                HIp&amp;#039; : menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (S p&amp;#039; + n) (S p&amp;#039; + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true *)&lt;br /&gt;
    rewrite HIp&amp;#039;.            (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.7. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat (S n) 0 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_distinto_0 : forall n:nat,&lt;br /&gt;
  iguales_nat (S n) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.     (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat (S n) 0 = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.8. Demostrar que &lt;br /&gt;
      forall n:nat, 1 * n = n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_1_n: forall n:nat, 1 * n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.          (* n : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       1 * n = n *)&lt;br /&gt;
  simpl.            (* n + 0 = n *)&lt;br /&gt;
  rewrite suma_n_0. (* n + 0 = n + 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.9. Demostrar que &lt;br /&gt;
       forall b c : bool, disyuncion (conjuncion b c)&lt;br /&gt;
                              (disyuncion (negacion b)&lt;br /&gt;
                                          (negacion c))&lt;br /&gt;
                          = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem alternativas: forall b c : bool,&lt;br /&gt;
    disyuncion&lt;br /&gt;
      (conjuncion b c)&lt;br /&gt;
      (disyuncion (negacion b)&lt;br /&gt;
                  (negacion c))&lt;br /&gt;
    = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; true) || (negacion true || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; false) || (negacion true || negacion false) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; true) || (negacion false || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; false) || (negacion false || negacion false)=true *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.10. Demostrar que &lt;br /&gt;
      forall n m p : nat, (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_suma_distributiva_d: forall n m p : nat,&lt;br /&gt;
  (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (n + m) * p = n * p + m * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (0 + m) * p = 0 * p + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                HIn&amp;#039; : (n&amp;#039; + m) * p = n&amp;#039; * p + m * p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (S n&amp;#039; + m) * p = S n&amp;#039; * p + m * p *)&lt;br /&gt;
    simpl.                   (* p + (n&amp;#039; + m) * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* p + (n&amp;#039; * p + m * p) = (p + n&amp;#039;) * p + m * p *)&lt;br /&gt;
    rewrite suma_asociativa. (* (p + n&amp;#039; * p) + m * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.11. Demostrar que &lt;br /&gt;
      forall n m p : nat, n * (m * p) = (n * m) * p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_asociativa: forall n m p : nat,&lt;br /&gt;
  n * (m * p) = (n * m) * p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.     (* n, m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n * (m * p) = (n * m) * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                 (* m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       0 * (m * p) = (0 * m) * p *)&lt;br /&gt;
    simpl.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* n&amp;#039;, m, p : nat&lt;br /&gt;
                       HIn&amp;#039; : n&amp;#039; * (m * p) = (n&amp;#039; * m) * p&lt;br /&gt;
                       ============================&lt;br /&gt;
                       S n&amp;#039; * (m * p) = (S n&amp;#039; * m) * p *)&lt;br /&gt;
    simpl.          (* m * p + n&amp;#039; * (m * p) = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.   (* m * p + (n&amp;#039; * m) * p = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite producto_suma_distributiva_d.&lt;br /&gt;
                    (* m * p + (n&amp;#039; * m) * p = m * p + (n&amp;#039; * m) * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 11. La táctica replace permite especificar el subtérmino&lt;br /&gt;
   que se desea reescribir y su sustituto: &lt;br /&gt;
      replace t with u&lt;br /&gt;
   sustituye todas las copias de la expresión t en el objetivo por la&lt;br /&gt;
   expresión u y añade la ecuación (t = u) como un nuevo subojetivo. &lt;br /&gt;
 &lt;br /&gt;
   El uso de la táctica replace es especialmente útil cuando la táctica &lt;br /&gt;
   rewrite actúa sobre una parte del objetivo que no es la que se desea. &lt;br /&gt;
&lt;br /&gt;
   Demostrar, usando la táctica replace y sin usar &lt;br /&gt;
   [assert (n + m = m + n)], que&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada&amp;#039; : forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.                 (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = (m + n) + p *)&lt;br /&gt;
  replace (n + m) with (m + n). &lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   m + n = n + m *)&lt;br /&gt;
    rewrite suma_conmutativa.   (* n + m = n + m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Teorías: Las teorías se importan con &amp;lt;code&amp;gt;Require Export Nombre&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;assert (H: P)&amp;lt;/code&amp;gt;: Incluyed la demostración de la propiedad P y continúa la demostración añadiendo como premisa la propiedad P con nombre H.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct b&amp;lt;/code&amp;gt;: Distingue dos casos según que b sea True o False.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct n as [| n&amp;#039;]&amp;lt;/code&amp;gt;: Distingue dos casos según que n sea 0 o sea &amp;lt;code&amp;gt;S n&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;induction n as [|n&amp;#039; IHn&amp;#039;]&amp;lt;/code&amp;gt;: Inicia una demostración por inducción sobre n. El caso base en n = 0. El paso de la inducción consiste en suponer la propiedad para n&amp;#039; y demostrarla para S n&amp;#039;. El nombre de la hipótesis de inducción es IHn&amp;#039;. &lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=46</id>
		<title>Tema 2: Demostraciones por inducción sobre los números naturales en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=46"/>
		<updated>2018-07-31T12:59:11Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: /* Tácticas de demostración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos cómo demostrar en Coq propiedades de funciones definidas sobre los números naturales. El principal método de demostración que se utiliza es el de inducción.&lt;br /&gt;
&lt;br /&gt;
= Contenido =&lt;br /&gt;
&lt;br /&gt;
1. Demostraciones por inducción &lt;br /&gt;
2. Demostraciones anidadas&lt;br /&gt;
3. Demostraciones formales vs demostraciones informales&lt;br /&gt;
4. Ejercicios complementarios &lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T2_Induccion.v|T2Induccion.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T2: Demostraciones por inducción sobre los números naturales en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T1_PF_en_Coq.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Demostraciones por inducción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n = n + 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento: con métodos elementales *)&lt;br /&gt;
Theorem suma_n_0_a: forall n:nat, n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento: con casos *)&lt;br /&gt;
Theorem suma_n_0_b : forall n:nat,&lt;br /&gt;
  n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            n = n + 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                            0 = 0 + 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S n&amp;#039; + 0  *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 3ª intento: con inducción *)&lt;br /&gt;
Theorem suma_n_0 : forall n:nat,&lt;br /&gt;
    n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = n + 0 *) &lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*   &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; = n&amp;#039; + 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; = S n&amp;#039; + 0 *)&lt;br /&gt;
    simpl.                    (* S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.          (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que&lt;br /&gt;
      forall n, n - n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem resta_n_n: forall n, n - n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n - n = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*  &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 - 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; - n&amp;#039; = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; - S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.                    (* n&amp;#039; - n&amp;#039; = 0 *)&lt;br /&gt;
    rewrite -&amp;gt; IHn&amp;#039;.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n * 0 = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem multiplica_n_0: forall n:nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * 0 = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * 0 = 0 *)&lt;br /&gt;
    reflexivity.      &lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; * 0 = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * 0 = 0 *)   &lt;br /&gt;
    simpl.                    (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    rewrite IHn&amp;#039;.             (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar que, &lt;br /&gt;
      forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_Sm: forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                (*  n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S (n + m) = n + S m *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S (0 + m) = 0 + S m *)&lt;br /&gt;
    simpl.                   (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S m = S m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* S (S n&amp;#039; + m) = S n&amp;#039; + S m *)&lt;br /&gt;
    simpl.                   (* S (S (n&amp;#039; + m)) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (n&amp;#039; + S m) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.3. Demostrar que &lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_conmutativa: forall n m : nat,&lt;br /&gt;
  n + m = m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros  n m.               (* n, m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + m = m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + m = m + 0 *)&lt;br /&gt;
    simpl.                   (* m = m + 0 *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_0.     (* m = m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + m = m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + m) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (m + n&amp;#039;) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_Sm.    (* S (m + n&amp;#039;) = S (m + n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.4. Demostrar que &lt;br /&gt;
      forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_asociativa: forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + (m + p) = (n + m) + p *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + (m + p) = (0 + m) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + (m + p) = n&amp;#039; + m + p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + (m + p) = (S n&amp;#039; + m) + p *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.5. Se considera la siguiente función que dobla su argumento. &lt;br /&gt;
      Fixpoint doble (n:nat) :=&lt;br /&gt;
        match n with&lt;br /&gt;
        | O    =&amp;gt; O&lt;br /&gt;
        | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall n, doble n = n + n. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint doble (n:nat) :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; O&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Lemma doble_suma : forall n, doble n = n + n .&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble n = n + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : doble n&amp;#039; = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble (S n&amp;#039;) = S n&amp;#039; + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (S (doble n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (S (n&amp;#039; + n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite suma_n_Sm.       (* S (n&amp;#039; + S n&amp;#039;) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6. Demostrar que&lt;br /&gt;
      forall n : nat, esPar (S n) = negacion (esPar n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_S : forall n : nat,&lt;br /&gt;
  esPar (S n) = negacion (esPar n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S n) = negacion (esPar n) *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar 1 = negacion (esPar 0) *)&lt;br /&gt;
    simpl.                       (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                              (* n&amp;#039; : nat&lt;br /&gt;
                                    IHn&amp;#039; : esPar (S n&amp;#039;) = negacion (esPar n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (esPar (S n&amp;#039;)) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.                (* esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (negacion (esPar n&amp;#039;)) *)&lt;br /&gt;
    rewrite negacion_involutiva. (* esPar (S (S n&amp;#039;)) = esPar n&amp;#039; *)&lt;br /&gt;
    simpl.                       (* esPar n&amp;#039; = esPar n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Demostraciones anidadas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_suma&amp;#039;: forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.            (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
  assert (H: 0 + n = n). &lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 + n = n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            H : 0 + n = n&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
    rewrite -&amp;gt; H.        (* n * m = n * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall n m p q : nat, (n + m) + (p + q) = (m + n) + (p + q)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento sin assert*)&lt;br /&gt;
Theorem suma_reordenada_1: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.              (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  rewrite -&amp;gt; suma_conmutativa. (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  p + q + (n + m) = m + n + (p + q) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento con assert *)&lt;br /&gt;
Theorem suma_reordenada: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.                (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  assert (H: n + m = m + n).&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    n + m = m + n *)&lt;br /&gt;
    rewrite -&amp;gt; suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    H : n + m = m + n&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
    rewrite -&amp;gt; H.                (* m + n + (p + q) = m + n + (p + q) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Demostraciones formales vs demostraciones informales&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + (m + p) = (0 + m) + p.&lt;br /&gt;
     Esto es consecuencia inmediata de la definición de suma.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + (m + p) = (n&amp;#039; + m) + p.                 &lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        (S n&amp;#039;) + (m + p) = ((S n&amp;#039;) + m) + p.&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que por la hipótesis de inducción se reduce a&lt;br /&gt;
        S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + m = m + 0&lt;br /&gt;
     que, por la definición de la suma, se reduce a&lt;br /&gt;
        m = m + 0&lt;br /&gt;
     que se verifica por el lema suma_n_0.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        S n&amp;#039; + m = m + S n&amp;#039;&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + m) = m + S n&amp;#039;&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = m + S n&amp;#039;&lt;br /&gt;
     que, por el lema suma_n_Sm, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = S (m + n&amp;#039;)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. Demostrar que&lt;br /&gt;
      forall n:nat, true = iguales_nat n n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_n_n: forall n : nat, true = iguales_nat n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat n n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* true = iguales_nat n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente la demostración del ejercicio anterior.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        true = iguales_nat 0 0&lt;br /&gt;
     que se verifica por la definición de iguales_nat.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) &lt;br /&gt;
     que, por la definición de iguales_nat, se reduce a&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        true = true&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar, usando assert pero no induct,&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada: forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof. &lt;br /&gt;
  intros n m p.               (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m + p = m + n + p *)&lt;br /&gt;
  assert (H : n + m = m + n). &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m = m + n *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 H : n + m = m + n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = (m + n) + p *)&lt;br /&gt;
    rewrite H.                (* (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.2. Demostrar que la multiplicación es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma producto_n_1 : forall n: nat,&lt;br /&gt;
    n * 1 = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n * 1 = n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 * 1 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; * 1 = n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; * 1 = S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; * 1) = S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_1 : forall n : nat,&lt;br /&gt;
    n + 1 = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + 1 = S n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + 1 = 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                HIn&amp;#039; : n&amp;#039; + 1 = S n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + 1 = S (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + 1) = S (S n&amp;#039;) *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* S (S n&amp;#039;) = S (S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_n_Sm: forall n m : nat, &lt;br /&gt;
    n * (m + 1) = n * m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n * (m + 1) = n * m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  -                             (* m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 * (m + 1) = 0 * m + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n&amp;#039;, m : nat&lt;br /&gt;
                                   IHn&amp;#039; : n&amp;#039; * (m + 1) = n&amp;#039; * m + n&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; * (m + 1) = S n&amp;#039; * m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                      (* (m + 1) + n&amp;#039; * (m + 1) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.               (* (m + 1) + (n&amp;#039; * m + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* n&amp;#039; * m + ((m + 1) + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_asociativa. (* n&amp;#039; * m + (m + (1 + n&amp;#039;)) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.        (* n&amp;#039; * m + (m + (n&amp;#039; + 1)) = &lt;br /&gt;
                                   (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_n_1.           (* n&amp;#039; * m + (m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_asociativa.    (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_conmutativa: forall m n : nat,&lt;br /&gt;
  m * n = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * m = m * n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                           (* m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * m = m * 0 *)&lt;br /&gt;
    rewrite multiplica_n_0.   (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039;, m : nat&lt;br /&gt;
                                 HIn&amp;#039; : n&amp;#039; * m = m * n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    simpl.                    (* m + n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* m + m * n&amp;#039; = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.      (* m + m * n&amp;#039; = m * (n&amp;#039; + 1) *)&lt;br /&gt;
    rewrite producto_n_Sm.    (* m + m * n&amp;#039; = m * n&amp;#039; + m *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m * n&amp;#039; + m = m * n&amp;#039; + m *)&lt;br /&gt;
   reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.3. Demostrar que &lt;br /&gt;
      forall n : nat, true = menor_o_igual n n.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_refl: forall n : nat,&lt;br /&gt;
    true = menor_o_igual n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                    (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual n n *)&lt;br /&gt;
  induction n as [| n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039; : nat&lt;br /&gt;
                                 HIn&amp;#039; : true = menor_o_igual n&amp;#039; n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                    (* true = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* menor_o_igual n&amp;#039; n&amp;#039; = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.4. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat 0 (S n) = false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_S: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (S n) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat 0 (S n) = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.5. Demostrar que &lt;br /&gt;
      forall b : bool, conjuncion b false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_false_r : forall b : bool,&lt;br /&gt;
  conjuncion b false = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* b : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                    b &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    true &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    false &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.6. Demostrar que &lt;br /&gt;
      forall n m p : nat, menor_o_igual n m = true -&amp;gt; &lt;br /&gt;
                          menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_suma: forall n m p : nat,&lt;br /&gt;
  menor_o_igual n m = true -&amp;gt; menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H.            (* n, m, p : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (p + n) (p + m) = true *)&lt;br /&gt;
  induction p as [|p&amp;#039; HIp&amp;#039;].&lt;br /&gt;
  -                          (* n, m : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (0 + n) (0 + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual n m = true *)&lt;br /&gt;
    rewrite H.               (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n, m, p&amp;#039; : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                HIp&amp;#039; : menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (S p&amp;#039; + n) (S p&amp;#039; + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true *)&lt;br /&gt;
    rewrite HIp&amp;#039;.            (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.7. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat (S n) 0 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_distinto_0 : forall n:nat,&lt;br /&gt;
  iguales_nat (S n) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.     (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat (S n) 0 = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.8. Demostrar que &lt;br /&gt;
      forall n:nat, 1 * n = n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_1_n: forall n:nat, 1 * n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.          (* n : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       1 * n = n *)&lt;br /&gt;
  simpl.            (* n + 0 = n *)&lt;br /&gt;
  rewrite suma_n_0. (* n + 0 = n + 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.9. Demostrar que &lt;br /&gt;
       forall b c : bool, disyuncion (conjuncion b c)&lt;br /&gt;
                              (disyuncion (negacion b)&lt;br /&gt;
                                          (negacion c))&lt;br /&gt;
                          = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem alternativas: forall b c : bool,&lt;br /&gt;
    disyuncion&lt;br /&gt;
      (conjuncion b c)&lt;br /&gt;
      (disyuncion (negacion b)&lt;br /&gt;
                  (negacion c))&lt;br /&gt;
    = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; true) || (negacion true || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; false) || (negacion true || negacion false) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; true) || (negacion false || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; false) || (negacion false || negacion false)=true *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.10. Demostrar que &lt;br /&gt;
      forall n m p : nat, (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_suma_distributiva_d: forall n m p : nat,&lt;br /&gt;
  (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (n + m) * p = n * p + m * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (0 + m) * p = 0 * p + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                HIn&amp;#039; : (n&amp;#039; + m) * p = n&amp;#039; * p + m * p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (S n&amp;#039; + m) * p = S n&amp;#039; * p + m * p *)&lt;br /&gt;
    simpl.                   (* p + (n&amp;#039; + m) * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* p + (n&amp;#039; * p + m * p) = (p + n&amp;#039;) * p + m * p *)&lt;br /&gt;
    rewrite suma_asociativa. (* (p + n&amp;#039; * p) + m * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.11. Demostrar que &lt;br /&gt;
      forall n m p : nat, n * (m * p) = (n * m) * p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_asociativa: forall n m p : nat,&lt;br /&gt;
  n * (m * p) = (n * m) * p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.     (* n, m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n * (m * p) = (n * m) * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                 (* m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       0 * (m * p) = (0 * m) * p *)&lt;br /&gt;
    simpl.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* n&amp;#039;, m, p : nat&lt;br /&gt;
                       HIn&amp;#039; : n&amp;#039; * (m * p) = (n&amp;#039; * m) * p&lt;br /&gt;
                       ============================&lt;br /&gt;
                       S n&amp;#039; * (m * p) = (S n&amp;#039; * m) * p *)&lt;br /&gt;
    simpl.          (* m * p + n&amp;#039; * (m * p) = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.   (* m * p + (n&amp;#039; * m) * p = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite producto_suma_distributiva_d.&lt;br /&gt;
                    (* m * p + (n&amp;#039; * m) * p = m * p + (n&amp;#039; * m) * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 11. La táctica replace permite especificar el subtérmino&lt;br /&gt;
   que se desea reescribir y su sustituto: &lt;br /&gt;
      replace t with u&lt;br /&gt;
   sustituye todas las copias de la expresión t en el objetivo por la&lt;br /&gt;
   expresión u y añade la ecuación (t = u) como un nuevo subojetivo. &lt;br /&gt;
 &lt;br /&gt;
   El uso de la táctica replace es especialmente útil cuando la táctica &lt;br /&gt;
   rewrite actúa sobre una parte del objetivo que no es la que se desea. &lt;br /&gt;
&lt;br /&gt;
   Demostrar, usando la táctica replace y sin usar &lt;br /&gt;
   [assert (n + m = m + n)], que&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada&amp;#039; : forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.                 (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = (m + n) + p *)&lt;br /&gt;
  replace (n + m) with (m + n). &lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   m + n = n + m *)&lt;br /&gt;
    rewrite suma_conmutativa.   (* n + m = n + m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Teorías: Las teorías se importan con &amp;lt;code&amp;gt;Require Export Nombre&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;assert (H: P)&amp;lt;/code&amp;gt;: Incluye la demostración de la propiedad P y continúa la demostración añadiendo como premisa la propiedad P con nombre H.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct b&amp;lt;/code&amp;gt;: Distingue dos casos según que b sea True o False.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct n as [| n&amp;#039;]&amp;lt;/code&amp;gt;: Distingue dos casos según que n sea 0 o sea &amp;lt;code&amp;gt;S n&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;induction n as [|n&amp;#039; IHn&amp;#039;]&amp;lt;/code&amp;gt;: Inicia una demostración por inducción sobre n. El caso base en n = 0. El paso de la inducción consiste en suponer la propiedad para n&amp;#039; y demostrarla para S n&amp;#039;. El nombre de la hipótesis de inducción es IHn&amp;#039;. &lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=45</id>
		<title>Tema 2: Demostraciones por inducción sobre los números naturales en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_2:_Demostraciones_por_inducci%C3%B3n_sobre_los_n%C3%BAmeros_naturales_en_Coq&amp;diff=45"/>
		<updated>2018-07-31T12:58:41Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página creada con «En este tema se introduce mediante ejemplos cómo demostrar en Coq propiedades de funciones definidas sobre los números naturales. El principal método de demostración qu…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos cómo demostrar en Coq propiedades de funciones definidas sobre los números naturales. El principal método de demostración que se utiliza es el de inducción.&lt;br /&gt;
&lt;br /&gt;
= Contenido =&lt;br /&gt;
&lt;br /&gt;
1. Demostraciones por inducción &lt;br /&gt;
2. Demostraciones anidadas&lt;br /&gt;
3. Demostraciones formales vs demostraciones informales&lt;br /&gt;
4. Ejercicios complementarios &lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T2_Induccion.v|T2Induccion.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T2: Demostraciones por inducción sobre los números naturales en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T1_PF_en_Coq.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Demostraciones por inducción &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n = n + 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento: con métodos elementales *)&lt;br /&gt;
Theorem suma_n_0_a: forall n:nat, n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                n = n + 0 *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento: con casos *)&lt;br /&gt;
Theorem suma_n_0_b : forall n:nat,&lt;br /&gt;
  n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            n = n + 0 *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (* &lt;br /&gt;
                           ============================&lt;br /&gt;
                            0 = 0 + 0 *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                     (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S n&amp;#039; + 0  *)&lt;br /&gt;
    simpl.              (* n&amp;#039; : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 3ª intento: con inducción *)&lt;br /&gt;
Theorem suma_n_0 : forall n:nat,&lt;br /&gt;
    n = n + 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n = n + 0 *) &lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*   &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; = n&amp;#039; + 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; = S n&amp;#039; + 0 *)&lt;br /&gt;
    simpl.                    (* S n&amp;#039; = S (n&amp;#039; + 0) *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.          (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2. Demostrar que&lt;br /&gt;
      forall n, n - n = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem resta_n_n: forall n, n - n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n - n = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (*  &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 - 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; - n&amp;#039; = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; - S n&amp;#039; = 0 *)&lt;br /&gt;
    simpl.                    (* n&amp;#039; - n&amp;#039; = 0 *)&lt;br /&gt;
    rewrite -&amp;gt; IHn&amp;#039;.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.1. Demostrar que&lt;br /&gt;
      forall n:nat, n * 0 = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem multiplica_n_0: forall n:nat, n * 0 = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                   (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * 0 = 0 *)&lt;br /&gt;
  induction n as [| n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * 0 = 0 *)&lt;br /&gt;
    reflexivity.      &lt;br /&gt;
  +                           (* n&amp;#039; : nat&lt;br /&gt;
                                 IHn&amp;#039; : n&amp;#039; * 0 = 0&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * 0 = 0 *)   &lt;br /&gt;
    simpl.                    (* n&amp;#039; * 0 = 0 *)&lt;br /&gt;
    rewrite IHn&amp;#039;.             (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2. Demostrar que, &lt;br /&gt;
      forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_Sm: forall n m : nat, S (n + m) = n + (S m).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                (*  n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S (n + m) = n + S m *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S (0 + m) = 0 + S m *)&lt;br /&gt;
    simpl.                   (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S m = S m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* S (S n&amp;#039; + m) = S n&amp;#039; + S m *)&lt;br /&gt;
    simpl.                   (* S (S (n&amp;#039; + m)) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (n&amp;#039; + S m) = S (n&amp;#039; + S m) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.3. Demostrar que &lt;br /&gt;
      forall n m : nat, n + m = m + n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_conmutativa: forall n m : nat,&lt;br /&gt;
  n + m = m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros  n m.               (* n, m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + m = m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + m = m + 0 *)&lt;br /&gt;
    simpl.                   (* m = m + 0 *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_0.     (* m = m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + m = m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + m) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (m + n&amp;#039;) = m + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_Sm.    (* S (m + n&amp;#039;) = S (m + n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.4. Demostrar que &lt;br /&gt;
      forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_asociativa: forall n m p : nat, n + (m + p) = (n + m) + p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + (m + p) = (n + m) + p *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + (m + p) = (0 + m) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; + (m + p) = n&amp;#039; + m + p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + (m + p) = (S n&amp;#039; + m) + p *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.5. Se considera la siguiente función que dobla su argumento. &lt;br /&gt;
      Fixpoint doble (n:nat) :=&lt;br /&gt;
        match n with&lt;br /&gt;
        | O    =&amp;gt; O&lt;br /&gt;
        | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
        end.&lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      forall n, doble n = n + n. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint doble (n:nat) :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; O&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; S (S (doble n&amp;#039;))&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Lemma doble_suma : forall n, doble n = n + n .&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble n = n + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  +                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble 0 = 0 + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : doble n&amp;#039; = n&amp;#039; + n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                doble (S n&amp;#039;) = S n&amp;#039; + S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (S (doble n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S (S (n&amp;#039; + n&amp;#039;)) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    rewrite suma_n_Sm.       (* S (n&amp;#039; + S n&amp;#039;) = S (n&amp;#039; + S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6. Demostrar que&lt;br /&gt;
      forall n : nat, esPar (S n) = negacion (esPar n).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem esPar_S : forall n : nat,&lt;br /&gt;
  esPar (S n) = negacion (esPar n).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                      (* n : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S n) = negacion (esPar n) *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  +                              (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar 1 = negacion (esPar 0) *)&lt;br /&gt;
    simpl.                       (* &lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  +                              (* n&amp;#039; : nat&lt;br /&gt;
                                    IHn&amp;#039; : esPar (S n&amp;#039;) = negacion (esPar n&amp;#039;)&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (esPar (S n&amp;#039;)) *)&lt;br /&gt;
    rewrite IHn&amp;#039;.                (* esPar (S (S n&amp;#039;)) = &lt;br /&gt;
                                     negacion (negacion (esPar n&amp;#039;)) *)&lt;br /&gt;
    rewrite negacion_involutiva. (* esPar (S (S n&amp;#039;)) = esPar n&amp;#039; *)&lt;br /&gt;
    simpl.                       (* esPar n&amp;#039; = esPar n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Demostraciones anidadas&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1. Demostrar que&lt;br /&gt;
      forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_suma&amp;#039;: forall n m : nat, (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.            (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
  assert (H: 0 + n = n). &lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            ============================&lt;br /&gt;
                            0 + n = n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                      (* n, m : nat&lt;br /&gt;
                            H : 0 + n = n&lt;br /&gt;
                            ============================&lt;br /&gt;
                            (0 + n) * m = n * m *)&lt;br /&gt;
    rewrite -&amp;gt; H.        (* n * m = n * m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2. Demostrar que&lt;br /&gt;
      forall n m p q : nat, (n + m) + (p + q) = (m + n) + (p + q)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento sin assert*)&lt;br /&gt;
Theorem suma_reordenada_1: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.              (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  rewrite -&amp;gt; suma_conmutativa. (* n, m, p, q : nat&lt;br /&gt;
                                  ============================&lt;br /&gt;
                                  p + q + (n + m) = m + n + (p + q) *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento con assert *)&lt;br /&gt;
Theorem suma_reordenada: forall n m p q : nat,&lt;br /&gt;
  (n + m) + (p + q) = (m + n) + (p + q).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p q.                (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
  assert (H: n + m = m + n).&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    n + m = m + n *)&lt;br /&gt;
    rewrite -&amp;gt; suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                              (* n, m, p, q : nat&lt;br /&gt;
                                    H : n + m = m + n&lt;br /&gt;
                                    ============================&lt;br /&gt;
                                    (n + m) + (p + q) = (m + n) + (p + q) *)&lt;br /&gt;
    rewrite -&amp;gt; H.                (* m + n + (p + q) = m + n + (p + q) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Demostraciones formales vs demostraciones informales&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.4.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + (m + p) = (0 + m) + p.&lt;br /&gt;
     Esto es consecuencia inmediata de la definición de suma.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + (m + p) = (n&amp;#039; + m) + p.                 &lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        (S n&amp;#039;) + (m + p) = ((S n&amp;#039;) + m) + p.&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + (m + p)) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que por la hipótesis de inducción se reduce a&lt;br /&gt;
        S ((n&amp;#039; + m) + p) = S ((n&amp;#039; + m) + p)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente a la demostración formal de la asociatividad de la&lt;br /&gt;
   suma del ejercicio 1.3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        0 + m = m + 0&lt;br /&gt;
     que, por la definición de la suma, se reduce a&lt;br /&gt;
        m = m + 0&lt;br /&gt;
     que se verifica por el lema suma_n_0.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        n&amp;#039; + m = m + n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        S n&amp;#039; + m = m + S n&amp;#039;&lt;br /&gt;
     que, por la definición de suma, se reduce a&lt;br /&gt;
        S (n&amp;#039; + m) = m + S n&amp;#039;&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = m + S n&amp;#039;&lt;br /&gt;
     que, por el lema suma_n_Sm, se reduce a&lt;br /&gt;
        S (m + n&amp;#039;) = S (m + n&amp;#039;)&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. Demostrar que&lt;br /&gt;
      forall n:nat, true = iguales_nat n n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem iguales_n_n: forall n : nat, true = iguales_nat n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.                  (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat n n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* true = iguales_nat n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- IHn&amp;#039;.         (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.4. Escribir la demostración informal (en lenguaje natural)&lt;br /&gt;
   correspondiente la demostración del ejercicio anterior.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* Demostración por inducción en n.&lt;br /&gt;
&lt;br /&gt;
   - Caso base: Se supone que n es 0 y hay que demostrar que&lt;br /&gt;
        true = iguales_nat 0 0&lt;br /&gt;
     que se verifica por la definición de iguales_nat.&lt;br /&gt;
&lt;br /&gt;
   - Paso de indución: Suponemos la hipótesis de inducción&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&amp;#039;&lt;br /&gt;
     Hay que demostrar que&lt;br /&gt;
        true = iguales_nat (S n&amp;#039;) (S n&amp;#039;) &lt;br /&gt;
     que, por la definición de iguales_nat, se reduce a&lt;br /&gt;
        true = iguales_nat n&amp;#039; n&lt;br /&gt;
     que, por la hipótesis de inducción, se reduce a&lt;br /&gt;
        true = true&lt;br /&gt;
     que es una identidad. *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 4. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.1. Demostrar, usando assert pero no induct,&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada: forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof. &lt;br /&gt;
  intros n m p.               (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.    (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m + p = m + n + p *)&lt;br /&gt;
  assert (H : n + m = m + n). &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n + m = m + n *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m + n = m + n *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -                           (* n, m, p : nat&lt;br /&gt;
                                 H : n + m = m + n&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 (n + m) + p = (m + n) + p *)&lt;br /&gt;
    rewrite H.                (* (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.2. Demostrar que la multiplicación es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma producto_n_1 : forall n: nat,&lt;br /&gt;
    n * 1 = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n * 1 = n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 * 1 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                IHn&amp;#039; : n&amp;#039; * 1 = n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; * 1 = S n&amp;#039; *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; * 1) = S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.            (* S n&amp;#039; = S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_n_1 : forall n : nat,&lt;br /&gt;
    n + 1 = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                   (* n : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                n + 1 = S n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* &lt;br /&gt;
                                ============================&lt;br /&gt;
                                0 + 1 = 1 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039; : nat&lt;br /&gt;
                                HIn&amp;#039; : n&amp;#039; + 1 = S n&amp;#039;&lt;br /&gt;
                                ============================&lt;br /&gt;
                                S n&amp;#039; + 1 = S (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                   (* S (n&amp;#039; + 1) = S (S n&amp;#039;) *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* S (S n&amp;#039;) = S (S n&amp;#039;) *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_n_Sm: forall n m : nat, &lt;br /&gt;
    n * (m + 1) = n * m + n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                   (* n, m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n * (m + 1) = n * m + n *)&lt;br /&gt;
  induction n as [|n&amp;#039; IHn&amp;#039;].&lt;br /&gt;
  -                             (* m : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   0 * (m + 1) = 0 * m + 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n&amp;#039;, m : nat&lt;br /&gt;
                                   IHn&amp;#039; : n&amp;#039; * (m + 1) = n&amp;#039; * m + n&amp;#039;&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   S n&amp;#039; * (m + 1) = S n&amp;#039; * m + S n&amp;#039; *)&lt;br /&gt;
    simpl.                      (* (m + 1) + n&amp;#039; * (m + 1) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite IHn&amp;#039;.               (* (m + 1) + (n&amp;#039; * m + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* n&amp;#039; * m + ((m + 1) + n&amp;#039;) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_asociativa. (* n&amp;#039; * m + (m + (1 + n&amp;#039;)) = &lt;br /&gt;
                                    (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.        (* n&amp;#039; * m + (m + (n&amp;#039; + 1)) = &lt;br /&gt;
                                   (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_n_1.           (* n&amp;#039; * m + (m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_permutada.     (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    rewrite suma_asociativa.    (* m + (n&amp;#039; * m + S n&amp;#039;) = (m + n&amp;#039; * m) + S n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem producto_conmutativa: forall m n : nat,&lt;br /&gt;
  m * n = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.                 (* n, m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 n * m = m * n *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                           (* m : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 0 * m = m * 0 *)&lt;br /&gt;
    rewrite multiplica_n_0.   (* 0 * m = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039;, m : nat&lt;br /&gt;
                                 HIn&amp;#039; : n&amp;#039; * m = m * n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 S n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    simpl.                    (* m + n&amp;#039; * m = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* m + m * n&amp;#039; = m * S n&amp;#039; *)&lt;br /&gt;
    rewrite &amp;lt;- suma_n_1.      (* m + m * n&amp;#039; = m * (n&amp;#039; + 1) *)&lt;br /&gt;
    rewrite producto_n_Sm.    (* m + m * n&amp;#039; = m * n&amp;#039; + m *)&lt;br /&gt;
    rewrite suma_conmutativa. (* m * n&amp;#039; + m = m * n&amp;#039; + m *)&lt;br /&gt;
   reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.3. Demostrar que &lt;br /&gt;
      forall n : nat, true = menor_o_igual n n.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_refl: forall n : nat,&lt;br /&gt;
    true = menor_o_igual n n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.                    (* n : nat&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual n n *)&lt;br /&gt;
  induction n as [| n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                           (* &lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual 0 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                           (* n&amp;#039; : nat&lt;br /&gt;
                                 HIn&amp;#039; : true = menor_o_igual n&amp;#039; n&amp;#039;&lt;br /&gt;
                                 ============================&lt;br /&gt;
                                 true = menor_o_igual (S n&amp;#039;) (S n&amp;#039;) *)&lt;br /&gt;
    simpl.                    (* true = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    rewrite HIn&amp;#039;.             (* menor_o_igual n&amp;#039; n&amp;#039; = menor_o_igual n&amp;#039; n&amp;#039; *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.4. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat 0 (S n) = false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_S: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (S n) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat 0 (S n) = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.5. Demostrar que &lt;br /&gt;
      forall b : bool, conjuncion b false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_false_r : forall b : bool,&lt;br /&gt;
  conjuncion b false = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* b : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                    b &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
  destruct b.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    true &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                    false &amp;amp;&amp;amp; false = false *)&lt;br /&gt;
    simpl.       (* false = false *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed. &lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.6. Demostrar que &lt;br /&gt;
      forall n m p : nat, menor_o_igual n m = true -&amp;gt; &lt;br /&gt;
                          menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem menor_o_igual_suma: forall n m p : nat,&lt;br /&gt;
  menor_o_igual n m = true -&amp;gt; menor_o_igual (p + n) (p + m) = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p H.            (* n, m, p : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (p + n) (p + m) = true *)&lt;br /&gt;
  induction p as [|p&amp;#039; HIp&amp;#039;].&lt;br /&gt;
  -                          (* n, m : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (0 + n) (0 + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual n m = true *)&lt;br /&gt;
    rewrite H.               (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n, m, p&amp;#039; : nat&lt;br /&gt;
                                H : menor_o_igual n m = true&lt;br /&gt;
                                HIp&amp;#039; : menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true&lt;br /&gt;
                                ============================&lt;br /&gt;
                                menor_o_igual (S p&amp;#039; + n) (S p&amp;#039; + m) = true *)&lt;br /&gt;
    simpl.                   (* menor_o_igual (p&amp;#039; + n) (p&amp;#039; + m) = true *)&lt;br /&gt;
    rewrite HIp&amp;#039;.            (* true = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.7. Demostrar que &lt;br /&gt;
      forall n : nat, iguales_nat (S n) 0 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem S_distinto_0 : forall n:nat,&lt;br /&gt;
  iguales_nat (S n) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.     (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  iguales_nat (S n) 0 = false *)&lt;br /&gt;
  simpl.       (* false = false *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.8. Demostrar que &lt;br /&gt;
      forall n:nat, 1 * n = n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_1_n: forall n:nat, 1 * n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intro n.          (* n : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       1 * n = n *)&lt;br /&gt;
  simpl.            (* n + 0 = n *)&lt;br /&gt;
  rewrite suma_n_0. (* n + 0 = n + 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.9. Demostrar que &lt;br /&gt;
       forall b c : bool, disyuncion (conjuncion b c)&lt;br /&gt;
                              (disyuncion (negacion b)&lt;br /&gt;
                                          (negacion c))&lt;br /&gt;
                          = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem alternativas: forall b c : bool,&lt;br /&gt;
    disyuncion&lt;br /&gt;
      (conjuncion b c)&lt;br /&gt;
      (disyuncion (negacion b)&lt;br /&gt;
                  (negacion c))&lt;br /&gt;
    = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; true) || (negacion true || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (true &amp;amp;&amp;amp; false) || (negacion true || negacion false) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; true) || (negacion false || negacion true) = true *)&lt;br /&gt;
  - reflexivity. (* (false &amp;amp;&amp;amp; false) || (negacion false || negacion false)=true *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.10. Demostrar que &lt;br /&gt;
      forall n m p : nat, (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_suma_distributiva_d: forall n m p : nat,&lt;br /&gt;
  (n + m) * p = (n * p) + (m * p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.              (* n, m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (n + m) * p = n * p + m * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;]. &lt;br /&gt;
  -                          (* m, p : nat&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (0 + m) * p = 0 * p + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                          (* n&amp;#039;, m, p : nat&lt;br /&gt;
                                HIn&amp;#039; : (n&amp;#039; + m) * p = n&amp;#039; * p + m * p&lt;br /&gt;
                                ============================&lt;br /&gt;
                                (S n&amp;#039; + m) * p = S n&amp;#039; * p + m * p *)&lt;br /&gt;
    simpl.                   (* p + (n&amp;#039; + m) * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.            (* p + (n&amp;#039; * p + m * p) = (p + n&amp;#039;) * p + m * p *)&lt;br /&gt;
    rewrite suma_asociativa. (* (p + n&amp;#039; * p) + m * p = (p + n&amp;#039; * p) + m * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 4.11. Demostrar que &lt;br /&gt;
      forall n m p : nat, n * (m * p) = (n * m) * p.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_asociativa: forall n m p : nat,&lt;br /&gt;
  n * (m * p) = (n * m) * p.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.     (* n, m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       n * (m * p) = (n * m) * p *)&lt;br /&gt;
  induction n as [|n&amp;#039; HIn&amp;#039;].&lt;br /&gt;
  -                 (* m, p : nat&lt;br /&gt;
                       ============================&lt;br /&gt;
                       0 * (m * p) = (0 * m) * p *)&lt;br /&gt;
    simpl.          (* 0 = 0 *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                 (* n&amp;#039;, m, p : nat&lt;br /&gt;
                       HIn&amp;#039; : n&amp;#039; * (m * p) = (n&amp;#039; * m) * p&lt;br /&gt;
                       ============================&lt;br /&gt;
                       S n&amp;#039; * (m * p) = (S n&amp;#039; * m) * p *)&lt;br /&gt;
    simpl.          (* m * p + n&amp;#039; * (m * p) = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite HIn&amp;#039;.   (* m * p + (n&amp;#039; * m) * p = (m + n&amp;#039; * m) * p *)&lt;br /&gt;
    rewrite producto_suma_distributiva_d.&lt;br /&gt;
                    (* m * p + (n&amp;#039; * m) * p = m * p + (n&amp;#039; * m) * p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 11. La táctica replace permite especificar el subtérmino&lt;br /&gt;
   que se desea reescribir y su sustituto: &lt;br /&gt;
      replace t with u&lt;br /&gt;
   sustituye todas las copias de la expresión t en el objetivo por la&lt;br /&gt;
   expresión u y añade la ecuación (t = u) como un nuevo subojetivo. &lt;br /&gt;
 &lt;br /&gt;
   El uso de la táctica replace es especialmente útil cuando la táctica &lt;br /&gt;
   rewrite actúa sobre una parte del objetivo que no es la que se desea. &lt;br /&gt;
&lt;br /&gt;
   Demostrar, usando la táctica replace y sin usar &lt;br /&gt;
   [assert (n + m = m + n)], que&lt;br /&gt;
      forall n m p : nat, n + (m + p) = m + (n + p).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_permutada&amp;#039; : forall n m p : nat,&lt;br /&gt;
  n + (m + p) = m + (n + p).&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m p.                 (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   n + (m + p) = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = m + (n + p) *)&lt;br /&gt;
  rewrite suma_asociativa.      (* (n + m) + p = (m + n) + p *)&lt;br /&gt;
  replace (n + m) with (m + n). &lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   (m + n) + p = (m + n) + p *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -                             (* n, m, p : nat&lt;br /&gt;
                                   ============================&lt;br /&gt;
                                   m + n = n + m *)&lt;br /&gt;
    rewrite suma_conmutativa.   (* n + m = n + m *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed. &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Teorías: Las teorías se importan con &amp;lt;code&amp;gt;Require Export Nombre&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;assert (H: P)&amp;lt;/code&amp;gt;: Incluyed la demostración de la propiedad P y continúa la demostración añadiendo como premisa la propiedad P con nombre H.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct b&amp;lt;/code&amp;gt;: Distingue dos casos según que b sea True o False.&lt;br /&gt;
* &amp;lt;code&amp;gt;destruct n as [| n&amp;#039;]&amp;lt;/code&amp;gt;: Distingue dos casos según que n sea 0 o sea &amp;lt;code&amp;gt;S n&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;induction n as [|n&amp;#039; IHn&amp;#039;]&amp;lt;/code&amp;gt;: Inicia una demostración por inducción sobre n. El caso base en n = 0. El paso de la inducción consiste en suponer la propiedad para n&amp;#039; y demostrarla para S n&amp;#039;. El nombre de la hipótesis de inducción es IHn&amp;#039;. &lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=44</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=44"/>
		<updated>2018-07-31T12:58:11Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;br /&gt;
* [[Tema 2: Demostraciones por inducción sobre los números naturales en Coq]].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=43</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=43"/>
		<updated>2018-07-31T12:10:59Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
= Contenido =&lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
+ &amp;lt;code&amp;gt;destruct b&amp;lt;/code&amp;gt;: Distingue dos casos según que b sea True o False.&lt;br /&gt;
+ &amp;lt;code&amp;gt;destruct n as [| n&amp;#039;]&amp;lt;/code&amp;gt;: Distingue dos casos según que n sea 0 o sea &amp;lt;code&amp;gt;S n&amp;#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=42</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=42"/>
		<updated>2018-07-31T12:01:53Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
= Contenido =&lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
= Teoría =&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Resumen =&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
== Definiciones ==&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Evaluación de expresiones ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Enunciados ==&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Estructura de demostraciones ==&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tácticas de demostración ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
= Referencias =&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=41</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=41"/>
		<updated>2018-07-31T11:59:39Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resumen ===&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
==== Definiciones ====&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos: Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Evaluación de expresiones ====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Enunciados ====&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Estructura de demostraciones ====&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tácticas de demostración ====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=40</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=40"/>
		<updated>2018-07-31T11:57:50Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resumen ===&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
==== Definiciones ====&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos&lt;br /&gt;
&lt;br /&gt;
Los módulos se inician con &amp;lt;code&amp;gt;Module Nombre.&amp;lt;/code&amp;gt; y terminan con &amp;lt;code&amp;gt;End Nombre&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Evaluación de expresiones ====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;/code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;Compute e&amp;lt;/code&amp;gt; escribe el valor de la expresión &amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Enunciados ====&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&lt;br /&gt;
&lt;br /&gt;
* El mismo patrón para &amp;lt;code&amp;gt;Example&amp;lt;/code&amp;gt; y &amp;lt;code&amp;gt;Lemma&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Estructura de demostraciones ====&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tácticas de demostración ====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;simpl&amp;lt;/code&amp;gt;: Simplifica las expresiones.&lt;br /&gt;
* &amp;lt;code&amp;gt;reflexivity&amp;lt;/code&amp;gt;: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* &amp;lt;code&amp;gt;intros vars&amp;lt;/code&amp;gt;: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite H&amp;lt;/code&amp;gt;: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* &amp;lt;code&amp;gt;rewrite &amp;lt;-H&amp;lt;/code&amp;gt;: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=39</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=39"/>
		<updated>2018-07-31T11:54:37Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: /* Evaluación de expresiones */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resumen ===&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
==== Definiciones ====&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos&lt;br /&gt;
&lt;br /&gt;
Los módulos se inician con `Module Nombre.` y terminan con `End Nombre`&lt;br /&gt;
&lt;br /&gt;
==== Evaluación de expresiones ====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Check e&amp;lt;/code&amp;gt; escribe el tipo de la expresión `e`.&lt;br /&gt;
* `Compute e` escribe el valor de la expresión `e`.&lt;br /&gt;
&lt;br /&gt;
==== Enunciados ====&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&lt;br /&gt;
&lt;br /&gt;
+ El mismo patrón para `Example` y `Lemma`&lt;br /&gt;
&lt;br /&gt;
==== Estructura de demostraciones ====&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tácticas de demostración ====&lt;br /&gt;
&lt;br /&gt;
* `simpl`: Simplifica las expresiones.&lt;br /&gt;
* `reflexivity`: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* `intros vars`: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* `rewrite H`: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* `rewrite &amp;lt;-H`: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=38</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=38"/>
		<updated>2018-07-31T11:51:27Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resumen ===&lt;br /&gt;
&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
==== Definiciones ====&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X args :=&lt;br /&gt;
        | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
        | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Definition nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Fixpoint nombre args: tipo :=&lt;br /&gt;
        cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      match d with&lt;br /&gt;
      | caso1 =&amp;gt; resultado1&lt;br /&gt;
      | caso2 =&amp;gt; resultado2&lt;br /&gt;
      ...&lt;br /&gt;
      | casoN =&amp;gt; resultadoN&lt;br /&gt;
      end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos&lt;br /&gt;
&lt;br /&gt;
Los módulos se inician con `Module Nombre.` y terminan con `End Nombre`&lt;br /&gt;
&lt;br /&gt;
==== Evaluación de expresiones ====&lt;br /&gt;
&lt;br /&gt;
* `Check e` escribe el tipo de la expresión `e`.&lt;br /&gt;
* `Compute e` escribe el valor de la expresión `e`.&lt;br /&gt;
&lt;br /&gt;
==== Enunciados ====&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Theorem nombre:&lt;br /&gt;
        cuerpo.&lt;br /&gt;
&amp;lt;/source&lt;br /&gt;
&lt;br /&gt;
+ El mismo patrón para `Example` y `Lemma`&lt;br /&gt;
&lt;br /&gt;
==== Estructura de demostraciones ====&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Proof.&lt;br /&gt;
        cuerpo&lt;br /&gt;
      Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tácticas de demostración ====&lt;br /&gt;
&lt;br /&gt;
* `simpl`: Simplifica las expresiones.&lt;br /&gt;
* `reflexivity`: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* `intros vars`: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* `rewrite H`: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* `rewrite &amp;lt;-H`: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=37</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=37"/>
		<updated>2018-07-31T11:49:54Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: /* Resumen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resumen ===&lt;br /&gt;
En esta sección se resumen las construcciones y tácticas utilizadas hasta ahora.&lt;br /&gt;
&lt;br /&gt;
==== Definiciones ====&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
      Inductive X  :=&lt;br /&gt;
        | constructor1 : X&lt;br /&gt;
        | constructor2 : X&lt;br /&gt;
        ...&lt;br /&gt;
        | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Inductive X args :=&lt;br /&gt;
  | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
  | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
  ...&lt;br /&gt;
  | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Definition nombre args: tipo :=&lt;br /&gt;
  cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Fixpoint nombre args: tipo :=&lt;br /&gt;
  cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
  match d with&lt;br /&gt;
  | caso1 =&amp;gt; resultado1&lt;br /&gt;
  | caso2 =&amp;gt; resultado2&lt;br /&gt;
  ...&lt;br /&gt;
  | casoN =&amp;gt; resultadoN&lt;br /&gt;
  end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos&lt;br /&gt;
&lt;br /&gt;
Los módulos se inician con `Module Nombre.` y terminan con `End Nombre`&lt;br /&gt;
&lt;br /&gt;
==== Evaluación de expresiones ====&lt;br /&gt;
&lt;br /&gt;
* `Check e` escribe el tipo de la expresión `e`.&lt;br /&gt;
* `Compute e` escribe el valor de la expresión `e`.&lt;br /&gt;
&lt;br /&gt;
==== Enunciados ====&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Theorem nombre:&lt;br /&gt;
  cuerpo.&lt;br /&gt;
&amp;lt;/source&lt;br /&gt;
&lt;br /&gt;
+ El mismo patrón para `Example` y `Lemma`&lt;br /&gt;
&lt;br /&gt;
==== Estructura de demostraciones ====&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Proof.&lt;br /&gt;
  cuerpo&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Proof.&lt;br /&gt;
  cuerpo&lt;br /&gt;
Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tácticas de demostración ====&lt;br /&gt;
&lt;br /&gt;
* `simpl`: Simplifica las expresiones.&lt;br /&gt;
* `reflexivity`: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* `intros vars`: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* `rewrite H`: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* `rewrite &amp;lt;-H`: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=36</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=36"/>
		<updated>2018-07-31T11:46:12Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (*  n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   1 + n = S n *)&lt;br /&gt;
  simpl.        (* S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* 0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                   n + n = m + m *)&lt;br /&gt;
  rewrite H.    (* m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                         n + m = m + o *)&lt;br /&gt;
  rewrite H1.         (* m + m = m + o *)&lt;br /&gt;
  rewrite H2.         (* o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                         (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite suma_O_n.   (* n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                   m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Resumen ===&lt;br /&gt;
&lt;br /&gt;
==== Definiciones ====&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos sin argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Inductive X  :=&lt;br /&gt;
  | constructor1 : X&lt;br /&gt;
  | constructor2 : X&lt;br /&gt;
  ...&lt;br /&gt;
  | constructorN : X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de tipos inductivos con argumentos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Inductive X args :=&lt;br /&gt;
  | constructor1 : args1 -&amp;gt; X&lt;br /&gt;
  | constructor2 : args2 -&amp;gt; X&lt;br /&gt;
  ...&lt;br /&gt;
  | constructorN : argsN -&amp;gt; X.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones no recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Definition nombre args: tipo :=&lt;br /&gt;
  cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Definición de funciones recursivas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Fixpoint nombre args: tipo :=&lt;br /&gt;
  cuerpo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Expresión con casos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
  match d with&lt;br /&gt;
  | caso1 =&amp;gt; resultado1&lt;br /&gt;
  | caso2 =&amp;gt; resultado2&lt;br /&gt;
  ...&lt;br /&gt;
  | casoN =&amp;gt; resultadoN&lt;br /&gt;
  end.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Módulos&lt;br /&gt;
&lt;br /&gt;
Los módulos se inician con `Module Nombre.` y terminan con `End Nombre`&lt;br /&gt;
&lt;br /&gt;
==== Evaluación de expresiones ====&lt;br /&gt;
&lt;br /&gt;
* `Check e` escribe el tipo de la expresión `e`.&lt;br /&gt;
* `Compute e` escribe el valor de la expresión `e`.&lt;br /&gt;
&lt;br /&gt;
==== Enunciados ====&lt;br /&gt;
&lt;br /&gt;
* Enunciados de teoremas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Theorem nombre:&lt;br /&gt;
  cuerpo.&lt;br /&gt;
&amp;lt;/source&lt;br /&gt;
&lt;br /&gt;
+ El mismo patrón para `Example` y `Lemma`&lt;br /&gt;
&lt;br /&gt;
==== Estructura de demostraciones ====&lt;br /&gt;
&lt;br /&gt;
* Demostración completa&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Proof.&lt;br /&gt;
  cuerpo&lt;br /&gt;
Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Demostración incompleta&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
Proof.&lt;br /&gt;
  cuerpo&lt;br /&gt;
Abort.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tácticas de demostración ====&lt;br /&gt;
&lt;br /&gt;
* `simpl`: Simplifica las expresiones.&lt;br /&gt;
* `reflexivity`: Demuestra el objetivo si es una igualdad trivial.&lt;br /&gt;
* `intros vars`: Introduce las variables del cuantificador universal y, como premisas, los antecedentes de las implicaciones. &lt;br /&gt;
* `rewrite H`: Sustituye el término izquierdo de H por el derecho.&lt;br /&gt;
* `rewrite &amp;lt;-H`: Sustituye el término derecho de H por el izquierdo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als. &lt;br /&gt;
&lt;br /&gt;
Otras referencias utilizadas son&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.cornell.edu/courses/cs3110/2018sp/a5/coq-tactics-cheatsheet.html Coq tactics cheatsheet].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T1_PF_en_Coq.v&amp;diff=35</id>
		<title>Archivo:T1 PF en Coq.v</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Archivo:T1_PF_en_Coq.v&amp;diff=35"/>
		<updated>2018-07-28T17:49:18Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Jalonso subió una nueva versión de Archivo:T1 PF en Coq.v&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=34</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=34"/>
		<updated>2018-07-28T17:47:45Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v|T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                    1 + n = S n *)&lt;br /&gt;
  simpl.        (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                    n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                    n + n = m + m *)&lt;br /&gt;
  rewrite -&amp;gt; H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                    m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                          n + m = m + o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.      (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                          m + m = m + o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.      (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                          o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                           (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite -&amp;gt; suma_O_n. (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                           n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                    m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                    m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                    S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=33</id>
		<title>Tema 1: Programación funcional y métodos elementales de demostración en Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Tema_1:_Programaci%C3%B3n_funcional_y_m%C3%A9todos_elementales_de_demostraci%C3%B3n_en_Coq&amp;diff=33"/>
		<updated>2018-07-28T17:44:55Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;En este tema se introduce mediante ejemplos la programación funcional en Coq y la demostración de las propiedades de las funciones definidas usando los métodos elementales de programación en Coq.&lt;br /&gt;
&lt;br /&gt;
=== Contenido === &lt;br /&gt;
&lt;br /&gt;
1. Datos y funciones&lt;br /&gt;
   1. Tipos enumerados  &lt;br /&gt;
   2. Booleanos  &lt;br /&gt;
   3. Tipos de las funciones  &lt;br /&gt;
   4. Tipos compuestos  &lt;br /&gt;
   5. Módulos  &lt;br /&gt;
   6. Números naturales  &lt;br /&gt;
2. Métodos elementales de demostración&lt;br /&gt;
   1. Demostraciones por simplificación &lt;br /&gt;
   2. Demostraciones por reescritura &lt;br /&gt;
   3. Demostraciones por análisis de casos &lt;br /&gt;
&lt;br /&gt;
=== Teoría ===&lt;br /&gt;
&lt;br /&gt;
La teoría correspondiente es [[Media:T1_PF_en_Coq.v]] cuyo contenido se muestra a continuación.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;coq&amp;quot;&amp;gt;&lt;br /&gt;
(* T1: Programación funcional y métodos elementales de demostración en Coq *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 1. Datos y funciones &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.1. Tipos enumerados  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.1. Definir el tipo dia cuyos constructores sean los días&lt;br /&gt;
   de la semana.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive dia: Type :=&lt;br /&gt;
  | lunes     : dia&lt;br /&gt;
  | martes    : dia&lt;br /&gt;
  | miercoles : dia&lt;br /&gt;
  | jueves    : dia&lt;br /&gt;
  | viernes   : dia&lt;br /&gt;
  | sabado    : dia&lt;br /&gt;
  | domingo   : dia.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.2. Definir la función &lt;br /&gt;
      siguiente_laborable : dia -&amp;gt; dia&lt;br /&gt;
   tal que (siguiente_laborable d) es el día laboral siguiente a d.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition siguiente_laborable (d:dia) : dia:=&lt;br /&gt;
  match d with&lt;br /&gt;
  | lunes     =&amp;gt; martes&lt;br /&gt;
  | martes    =&amp;gt; miercoles&lt;br /&gt;
  | miercoles =&amp;gt; jueves&lt;br /&gt;
  | jueves    =&amp;gt; viernes&lt;br /&gt;
  | viernes   =&amp;gt; lunes&lt;br /&gt;
  | sabado    =&amp;gt; lunes&lt;br /&gt;
  | domingo   =&amp;gt; lunes&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.3. Calcular el valor de las siguientes expresiones &lt;br /&gt;
      + siguiente_laborable jueves&lt;br /&gt;
      + siguiente_laborable viernes&lt;br /&gt;
      + siguiente_laborable (siguiente_laborable sabado)&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable jueves).&lt;br /&gt;
(* ==&amp;gt; viernes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable viernes).&lt;br /&gt;
(* ==&amp;gt; lunes : dia *)&lt;br /&gt;
&lt;br /&gt;
Compute (siguiente_laborable (siguiente_laborable sabado)).&lt;br /&gt;
(* ==&amp;gt; martes : dia *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.1.4. Demostrar que &lt;br /&gt;
      siguiente_laborable (siguiente_laborable sabado) = martes&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example siguiente_laborable1:&lt;br /&gt;
  siguiente_laborable (siguiente_laborable sabado) = martes.&lt;br /&gt;
Proof.&lt;br /&gt;
  simpl.       (* ⊢ martes = martes *)&lt;br /&gt;
  reflexivity. (* ⊢ *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.2. Booleanos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.1. Definir el tipo bool (𝔹) cuyos constructores son true&lt;br /&gt;
   y false. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive bool : Type :=&lt;br /&gt;
  | true  : bool&lt;br /&gt;
  | false : bool.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.2. Definir la función&lt;br /&gt;
      negacion : bool -&amp;gt; bool&lt;br /&gt;
   tal que (negacion b) es la negacion de b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition negacion (b:bool) : bool :=&lt;br /&gt;
  match b with&lt;br /&gt;
  | true  =&amp;gt; false&lt;br /&gt;
  | false =&amp;gt; true&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.3. Definir la función&lt;br /&gt;
      conjuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion b1 b2) es la conjuncion de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; b2&lt;br /&gt;
  | false =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.4. Definir la función&lt;br /&gt;
      disyuncion : bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (disyuncion b1 b2) es la disyunción de b1 y b2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition disyuncion (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  match b1 with&lt;br /&gt;
  | true  =&amp;gt; true&lt;br /&gt;
  | false =&amp;gt; b2&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.5. Demostrar las siguientes propiedades&lt;br /&gt;
      disyuncion true  false = true.&lt;br /&gt;
      disyuncion false false = false.&lt;br /&gt;
      disyuncion false true  = true.&lt;br /&gt;
      disyuncion true  true  = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion1: disyuncion true false = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion2: disyuncion false false = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion3: disyuncion false true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example disyuncion4: disyuncion true true = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.6. Definir los operadores (&amp;amp;&amp;amp;) y (||) como abreviaturas&lt;br /&gt;
   de las funciones conjuncion y disyuncion.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x &amp;amp;&amp;amp; y&amp;quot; := (conjuncion x y).&lt;br /&gt;
Notation &amp;quot;x || y&amp;quot; := (disyuncion x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.2.7. Demostrar que&lt;br /&gt;
      false || false || true = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example disyuncion5: false || false || true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.1. Definir la función &lt;br /&gt;
      nand : bool -&amp;gt; bool -&amp;gt; bool &lt;br /&gt;
   tal que (nanb x y) se verifica si x e y no son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de nand&lt;br /&gt;
      nand true  false = true.&lt;br /&gt;
      nand false false = true.&lt;br /&gt;
      nand false true  = true.&lt;br /&gt;
      nand true  true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition nand (b1:bool) (b2:bool) : bool :=&lt;br /&gt;
  negacion (b1 &amp;amp;&amp;amp; b2).&lt;br /&gt;
&lt;br /&gt;
Example nand1: nand true false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand2: nand false false = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand3: nand false true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example nand4: nand true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.2.2. Definir la función&lt;br /&gt;
      conjuncion3 : bool -&amp;gt; bool -&amp;gt; bool -&amp;gt; bool&lt;br /&gt;
   tal que (conjuncion3 x y z) se verifica si x, y y z son verdaderos.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades de conjuncion3&lt;br /&gt;
      conjuncion3 true  true  true  = true.&lt;br /&gt;
      conjuncion3 false true  true  = false.&lt;br /&gt;
      conjuncion3 true  false true  = false.&lt;br /&gt;
      conjuncion3 true  true  false = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition conjuncion3 (b1:bool) (b2:bool) (b3:bool) : bool :=&lt;br /&gt;
  b1 &amp;amp;&amp;amp; b2 &amp;amp;&amp;amp; b3.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3a: conjuncion3 true true true = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3b: conjuncion3 false true true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3c: conjuncion3 true false true = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example conjuncion3d: conjuncion3 true true false = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.3. Tipos de las funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.3.1. Calcular el tipo de las siguientes expresiones&lt;br /&gt;
      + true&lt;br /&gt;
      + (negacion true)&lt;br /&gt;
      + negacion&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check true.&lt;br /&gt;
(* ===&amp;gt; true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check (negacion true).&lt;br /&gt;
(* ===&amp;gt; negacion true : bool *)&lt;br /&gt;
&lt;br /&gt;
Check negacion.&lt;br /&gt;
(* ===&amp;gt; negacion : bool -&amp;gt; bool *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.4. Tipos compuestos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.1. Definir el tipo rva cuyos constructores son rojo, verde&lt;br /&gt;
   y azul. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive rva : Type :=&lt;br /&gt;
  | rojo  : rva&lt;br /&gt;
  | verde : rva&lt;br /&gt;
  | azul  : rva.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.2. Definir el tipo color cuyos constructores son negro,&lt;br /&gt;
   blanco y primario, donde primario es una función de rva en color.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive color : Type :=&lt;br /&gt;
  | negro    : color&lt;br /&gt;
  | blanco   : color&lt;br /&gt;
  | primario : rva -&amp;gt; color.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.3. Definir la función&lt;br /&gt;
      monocromático : color -&amp;gt; bool&lt;br /&gt;
   tal que (monocromático c) se verifica si c es monocromático.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition monocromático (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro      =&amp;gt; true&lt;br /&gt;
  | blanco     =&amp;gt; true&lt;br /&gt;
  | primario p =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.4.4. Definir la función&lt;br /&gt;
      esRojo : color -&amp;gt; bool&lt;br /&gt;
   tal que (esRojo c) se verifica si c es rojo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esRojo (c : color) : bool :=&lt;br /&gt;
  match c with&lt;br /&gt;
  | negro         =&amp;gt; false&lt;br /&gt;
  | blanco        =&amp;gt; false&lt;br /&gt;
  | primario rojo =&amp;gt; true&lt;br /&gt;
  | primario _    =&amp;gt; false&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.5. Módulos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.5.1. Iniciar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ 1.6. Números naturales  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.1. Definir el tipo nat de los números naturales con los&lt;br /&gt;
   constructores 0 (para el 0) y S (para el siguiente).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Inductive nat : Type :=&lt;br /&gt;
  | O : nat&lt;br /&gt;
  | S : nat -&amp;gt; nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.2. Definir la función&lt;br /&gt;
      pred : nat -&amp;gt; nat&lt;br /&gt;
   tal que (pred n) es el predecesor de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition pred (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.3. Finalizar el módulo Naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.4. Calcular el tipo y valor de la expresión &lt;br /&gt;
   (S (S (S (S O)))).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check (S (S (S (S O)))).&lt;br /&gt;
(* ===&amp;gt; 4 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.5. Definir la función&lt;br /&gt;
      menosDos : nat -&amp;gt; nat&lt;br /&gt;
   tal que (menosDos n) es n-2. &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menosDos (n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O        =&amp;gt; O&lt;br /&gt;
    | S O      =&amp;gt; O&lt;br /&gt;
    | S (S n&amp;#039;) =&amp;gt; n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.6. Evaluar la expresión (menosDos 4).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (menosDos 4).&lt;br /&gt;
(* ===&amp;gt; 2 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.7. Calcular et tipo de las funcionse S, pred y menosDos.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check S.&lt;br /&gt;
(* ===&amp;gt;  S : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check pred.&lt;br /&gt;
(* ===&amp;gt; pred : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
Check menosDos.&lt;br /&gt;
(* ===&amp;gt; menosDos : nat -&amp;gt; nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.8. Definir la función&lt;br /&gt;
      esPar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esPar n) se verifica si n es par.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint esPar (n:nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O        =&amp;gt; true&lt;br /&gt;
  | S O      =&amp;gt; false&lt;br /&gt;
  | S (S n&amp;#039;) =&amp;gt; esPar n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.9. Definir la función&lt;br /&gt;
      esImpar : nat -&amp;gt; bool&lt;br /&gt;
   tal que (esImpar n) se verifica si n es impar.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition esImpar (n:nat) : bool :=&lt;br /&gt;
  negacion (esPar n).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.10. Demostrar que&lt;br /&gt;
      + esImpar 1 = true.&lt;br /&gt;
      + esImpar 4 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example esImpar1: esImpar 1 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example esImpar2: esImpar 4 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.12. Iniciar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.13. Definir la función&lt;br /&gt;
      suma : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (suma n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      suma 3 2 = 5&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida plus&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint suma (n : nat) (m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; m&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; S (suma n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (suma 3 2).&lt;br /&gt;
(* ===&amp;gt; 5: nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.14. Definir la función&lt;br /&gt;
      producto : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (producto n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      producto 3 2 = 6&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint producto (n m : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O    =&amp;gt; O&lt;br /&gt;
    | S n&amp;#039; =&amp;gt; suma m (producto n&amp;#039; m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example producto1: (producto 2 3) = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.15. Definir la función&lt;br /&gt;
      resta : nat -&amp;gt; nat -&amp;gt; nat &lt;br /&gt;
   tal que (resta n m) es la diferencia de n y m. Por ejemplo,&lt;br /&gt;
      resta 3 2 = 1&lt;br /&gt;
&lt;br /&gt;
   Nota: Es equivalente a la predefinida minus.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Fixpoint resta (n m:nat) : nat :=&lt;br /&gt;
  match (n, m) with&lt;br /&gt;
  | (O   , _)    =&amp;gt; O&lt;br /&gt;
  | (S _ , O)    =&amp;gt; n&lt;br /&gt;
  | (S n&amp;#039;, S m&amp;#039;) =&amp;gt; resta n&amp;#039; m&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.16. Cerrar el módulo Naturales2.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
End Naturales2.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.17. Definir la función&lt;br /&gt;
      potencia : nat -&amp;gt;  nat -&amp;gt; nat&lt;br /&gt;
   tal que (potencia x n) es la potencia n-ésima de x. Por ejemplo,&lt;br /&gt;
      potencia 2 3 = 8&lt;br /&gt;
   &lt;br /&gt;
   Nota: En lugar de producto, usar la predefinida mult.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint potencia (x n : nat) : nat :=&lt;br /&gt;
  match n with&lt;br /&gt;
    | O   =&amp;gt; S O&lt;br /&gt;
    | S m =&amp;gt; mult x (potencia x m)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Compute (potencia 2 3).&lt;br /&gt;
(* ===&amp;gt; 8 : nat *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.1. Definir la función&lt;br /&gt;
      factorial : nat -&amp;gt; nat1&lt;br /&gt;
   tal que (factorial n) es el factorial de n. &lt;br /&gt;
      factorial 3 = 6.&lt;br /&gt;
      factorial 5 = mult 10 12&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint factorial (n:nat) : nat := &lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; 1&lt;br /&gt;
  | S n&amp;#039; =&amp;gt;  S n&amp;#039; * factorial n&amp;#039;&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial1: factorial 3 = 6.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_factorial2: factorial 5 = mult 10 12.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.18. Definir los operadores +, - y * como abreviaturas de&lt;br /&gt;
   las funciones plus, rminus y mult.  &lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;x + y&amp;quot; := (plus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x - y&amp;quot; := (minus x y)&lt;br /&gt;
                       (at level 50, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
Notation &amp;quot;x * y&amp;quot; := (mult x y)&lt;br /&gt;
                       (at level 40, left associativity)&lt;br /&gt;
                       : nat_scope.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.19. Definir la función&lt;br /&gt;
      iguales_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (iguales_nat n m) se verifica si n y me son iguales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint iguales_nat (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O =&amp;gt; match m with&lt;br /&gt;
         | O    =&amp;gt; true&lt;br /&gt;
         | S m&amp;#039; =&amp;gt; false&lt;br /&gt;
         end&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; iguales_nat n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.20. Definir la función&lt;br /&gt;
      menor_o_igual : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_o_igual n m) se verifica si n es menor o igual que m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint menor_o_igual (n m : nat) : bool :=&lt;br /&gt;
  match n with&lt;br /&gt;
  | O    =&amp;gt; true&lt;br /&gt;
  | S n&amp;#039; =&amp;gt; match m with&lt;br /&gt;
            | O    =&amp;gt; false&lt;br /&gt;
            | S m&amp;#039; =&amp;gt; menor_o_igual n&amp;#039; m&amp;#039;&lt;br /&gt;
            end&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 1.6.21. Demostrar las siguientes propiedades&lt;br /&gt;
      + menor_o_igual 2 2 = true.&lt;br /&gt;
      + menor_o_igual 2 4 = true.&lt;br /&gt;
      + menor_o_igual 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual1: menor_o_igual 2 2 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual2: menor_o_igual 2 4 = true.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_o_igual3: menor_o_igual 4 2 = false.&lt;br /&gt;
Proof. simpl. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 1.6.2. Definir la función&lt;br /&gt;
      menor_nat : nat -&amp;gt; nat -&amp;gt; bool&lt;br /&gt;
   tal que (menor_nat n m) se verifica si n es menor que m.&lt;br /&gt;
&lt;br /&gt;
   Demostrar las siguientes propiedades&lt;br /&gt;
      menor_nat 2 2 = false.&lt;br /&gt;
      menor_nat 2 4 = true.&lt;br /&gt;
      menor_nat 4 2 = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition menor_nat (n m : nat) : bool :=&lt;br /&gt;
  negacion (iguales_nat (m-n) 0).&lt;br /&gt;
&lt;br /&gt;
Example menor_nat1: (menor_nat 2 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat2: (menor_nat 2 4) = true.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example menor_nat3: (menor_nat 4 2) = false.&lt;br /&gt;
Proof. simpl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2. Métodos elementales de demostración&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.1. Demostraciones por simplificación &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.1. Demostrar que el 0 es el elemento neutro por la&lt;br /&gt;
   izquierda de la suma de los números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem suma_O_n : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  simpl.       (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   n = n *)&lt;br /&gt;
  reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem suma_O_n&amp;#039; : forall n : nat, 0 + n = n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                   0 + n = n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.2. Demostrar que la suma de 1 y n es el siguiente de n.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                    1 + n = S n *)&lt;br /&gt;
  simpl.        (* n : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                   S n = S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem suma_1_l&amp;#039; : forall n:nat, 1 + n = S n.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.     &lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.1.3. Demostrar que el producto de 0 por n es 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_l : forall n:nat, 0 * n = 0.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.    (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 * n = 0 *)&lt;br /&gt;
  simpl.       (* n : nat&lt;br /&gt;
                  ============================&lt;br /&gt;
                  0 = 0 *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.2. Demostraciones por reescritura &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.1. Demostrar que si n = m, entonces n + n = m + m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales : forall n m:nat,&lt;br /&gt;
  n = m -&amp;gt;&lt;br /&gt;
  n + n = m + m.&lt;br /&gt;
&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.   (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   ============================&lt;br /&gt;
                    n = m -&amp;gt; n + n = m + m *)&lt;br /&gt;
  intros H.     (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                    n + n = m + m *)&lt;br /&gt;
  rewrite -&amp;gt; H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : n = m&lt;br /&gt;
                   ============================&lt;br /&gt;
                    m + m = m + m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.1. Demostrar que si n = m y m = o, entonces &lt;br /&gt;
   n + m = m + o.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem suma_iguales_ejercicio : forall n m o : nat,&lt;br /&gt;
  n = m -&amp;gt; m = o -&amp;gt; n + m = m + o.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m o H1 H2. (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                          n + m = m + o *)&lt;br /&gt;
  rewrite -&amp;gt; H1.      (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                          m + m = m + o *)&lt;br /&gt;
  rewrite -&amp;gt; H2.      (* n : nat&lt;br /&gt;
                         m : nat&lt;br /&gt;
                         o : nat&lt;br /&gt;
                         H1 : n = m&lt;br /&gt;
                         H2 : m = o&lt;br /&gt;
                         ============================&lt;br /&gt;
                          o + o = o + o *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.2.2. Demostrar que (0 + n) * m = n * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_0_mas : forall n m : nat,&lt;br /&gt;
  (0 + n) * m = n * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m.          (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                           (0 + n) * m = n * m *)&lt;br /&gt;
  rewrite -&amp;gt; suma_O_n. (* n : nat&lt;br /&gt;
                          m : nat&lt;br /&gt;
                          ============================&lt;br /&gt;
                           n * m = n * m *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.2. Demostrar que si m = S n, entonces m * (1 + n) = m * m.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem producto_S_1 : forall n m : nat,&lt;br /&gt;
  m = S n -&amp;gt; m * (1 + n) = m * m.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n m H. (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                    m * (1 + n) = m * m *)&lt;br /&gt;
  simpl.        (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                    m * S n = m * m *)&lt;br /&gt;
  rewrite H.    (* n : nat&lt;br /&gt;
                   m : nat&lt;br /&gt;
                   H : m = S n&lt;br /&gt;
                   ============================&lt;br /&gt;
                    S n * S n = S n * S n *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 2.3. Demostraciones por análisis de casos &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.1. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero_primer_intento : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n. (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  simpl.    (* n : nat&lt;br /&gt;
               ============================&lt;br /&gt;
                iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
Abort.&lt;br /&gt;
&lt;br /&gt;
(* 2º intento *)&lt;br /&gt;
Theorem siguiente_distinto_cero : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros n.             (* n : nat&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (n + 1) 0 = false *)&lt;br /&gt;
  destruct n as [| n&amp;#039;]. &lt;br /&gt;
  -                     (*&lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
    reflexivity.       &lt;br /&gt;
  -                     (* n&amp;#039; : nat                           &lt;br /&gt;
                           ============================&lt;br /&gt;
                            iguales_nat (S n&amp;#039; + 1) 0 = false *)&lt;br /&gt;
    reflexivity.        &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.2. Demostrar que la negacion es involutiva; es decir, la&lt;br /&gt;
   negacion de la negacion de b es b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem negacion_involutiva : forall b : bool,&lt;br /&gt;
  negacion (negacion b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b.      (* &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion b) = b *)&lt;br /&gt;
  destruct b.    &lt;br /&gt;
  -              (* &lt;br /&gt;
                     ============================&lt;br /&gt;
                     negacion (negacion true) = true *)&lt;br /&gt;
    reflexivity.&lt;br /&gt;
  -              (*   &lt;br /&gt;
                    ============================&lt;br /&gt;
                     negacion (negacion false) = false *)   &lt;br /&gt;
    reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.3. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* 1ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; b *)&lt;br /&gt;
  destruct b.      &lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; true *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
  -                (* c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; c = c &amp;amp;&amp;amp; false *)&lt;br /&gt;
    destruct c.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                       ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; true = true &amp;amp;&amp;amp; false *)  &lt;br /&gt;
      reflexivity.&lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* 2ª demostración *)&lt;br /&gt;
Theorem conjuncion_commutativa2 : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
  { destruct c.&lt;br /&gt;
    { reflexivity. }&lt;br /&gt;
    { reflexivity. } }&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.4. Demostrar que &lt;br /&gt;
     conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_intercambio : forall b c d,&lt;br /&gt;
    conjuncion (conjuncion b c) d = conjuncion (conjuncion b d) c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c d.&lt;br /&gt;
  destruct b.&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false  = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.      &lt;br /&gt;
      - reflexivity.   (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (true &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (true &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - destruct c.&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; true *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true *)&lt;br /&gt;
    { destruct d.&lt;br /&gt;
      - reflexivity.   (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; true = (false &amp;amp;&amp;amp; true) &amp;amp;&amp;amp; false *)&lt;br /&gt;
      - reflexivity. } (* (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false = (false &amp;amp;&amp;amp; false) &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.5. Demostrar que n + 1 es distinto de 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem siguiente_distinto_cero&amp;#039; : forall n : nat,&lt;br /&gt;
  iguales_nat (n + 1) 0 = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [|n].&lt;br /&gt;
  - reflexivity. (* iguales_nat (0 + 1) 0 = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat (S n + 1) 0 = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo 2.3.6. Demostrar que la conjuncion es conmutativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_commutativa&amp;#039;&amp;#039; : forall b c,&lt;br /&gt;
    conjuncion b c = conjuncion c b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] [].&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* true  &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; true *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; true  = true  &amp;amp;&amp;amp; false *)&lt;br /&gt;
  - reflexivity. (* false &amp;amp;&amp;amp; false = false &amp;amp;&amp;amp; false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.3. Demostrar que si &lt;br /&gt;
      conjuncion b c = true, entonces c = true.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_true_elim : forall b c : bool,&lt;br /&gt;
  conjuncion b c = true -&amp;gt; c = true.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros b c.      (* b : bool&lt;br /&gt;
                      c : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; c = true -&amp;gt; c = true *)  &lt;br /&gt;
  destruct c.      &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; true = true -&amp;gt; true = true *)&lt;br /&gt;
    reflexivity.    &lt;br /&gt;
  -                (* b : bool&lt;br /&gt;
                      ============================&lt;br /&gt;
                       b &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
    destruct b.    &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       true &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (*   &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity. &lt;br /&gt;
    +              (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false &amp;amp;&amp;amp; false = true -&amp;gt; false = true *)&lt;br /&gt;
      simpl.       (* &lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true -&amp;gt; false = true *)&lt;br /&gt;
      intros H.    (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       false = true *)&lt;br /&gt;
      rewrite H.   (* H : false = true&lt;br /&gt;
                      ============================&lt;br /&gt;
                       true = true *)&lt;br /&gt;
      reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 2.2.4. Demostrar que 0 es distinto de n + 1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem cero_distinto_mas_uno: forall n : nat,&lt;br /&gt;
  iguales_nat 0 (n + 1) = false.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [| n&amp;#039;].&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (0 + 1) = false *)&lt;br /&gt;
  - reflexivity. (* iguales_nat 0 (S n&amp;#039; + 1) = false *)&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § 3. Ejercicios complementarios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.1. Demostrar que&lt;br /&gt;
      forall (f : bool -&amp;gt; bool),&lt;br /&gt;
        (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem aplica_dos_veces_la_identidad : forall (f : bool -&amp;gt; bool),&lt;br /&gt;
  (forall (x : bool), f x = x) -&amp;gt; forall (b : bool), f (f b) = b.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros f H b. (* f : bool -&amp;gt; bool&lt;br /&gt;
                   H : forall x : bool, f x = x&lt;br /&gt;
                   b : bool&lt;br /&gt;
                   ============================&lt;br /&gt;
                    f (f b) = b *)&lt;br /&gt;
  rewrite H.    (* f b = b *)&lt;br /&gt;
  rewrite H.    (* b = b *)&lt;br /&gt;
  reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.2. Demostrar que&lt;br /&gt;
      forall (b c : bool),&lt;br /&gt;
        (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem conjuncion_igual_disyuncion: forall (b c : bool),&lt;br /&gt;
  (conjuncion b c = disyuncion b c) -&amp;gt; b = c.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros [] c.   &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true &amp;amp;&amp;amp; c = true || c -&amp;gt; true = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = true -&amp;gt; true = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : c = true&lt;br /&gt;
                    ============================&lt;br /&gt;
                     true = true *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
  -              (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false &amp;amp;&amp;amp; c = false || c -&amp;gt; false = c *)&lt;br /&gt;
    simpl.       (* c : bool&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c -&amp;gt; false = c *)&lt;br /&gt;
    intros H.    (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     false = c *)&lt;br /&gt;
    rewrite H.   (* c : bool&lt;br /&gt;
                    H : false = c&lt;br /&gt;
                    ============================&lt;br /&gt;
                     c = c *)&lt;br /&gt;
    reflexivity. &lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio 3.3. En este ejercicio se considera la siguiente&lt;br /&gt;
   representación de los números naturales&lt;br /&gt;
      Inductive nat2 : Type :=&lt;br /&gt;
        | C  : nat2&lt;br /&gt;
        | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
        | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
   donde C representa el cero, D el doble y SD el siguiente del doble.&lt;br /&gt;
&lt;br /&gt;
   Definir la función&lt;br /&gt;
      nat2Anat : nat2 -&amp;gt; nat&lt;br /&gt;
   tal que (nat2Anat x) es el número natural representado por x. &lt;br /&gt;
&lt;br /&gt;
   Demostrar que &lt;br /&gt;
      nat2Anat (SD (SD C))     = 3&lt;br /&gt;
      nat2Anat (D (SD (SD C))) = 6.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive nat2 : Type :=&lt;br /&gt;
  | C  : nat2&lt;br /&gt;
  | D  : nat2 -&amp;gt; nat2&lt;br /&gt;
  | SD : nat2 -&amp;gt; nat2.&lt;br /&gt;
 &lt;br /&gt;
Fixpoint nat2Anat (x:nat2) : nat :=&lt;br /&gt;
  match x with&lt;br /&gt;
  | C    =&amp;gt; O&lt;br /&gt;
  | D n  =&amp;gt; 2 * nat2Anat n&lt;br /&gt;
  | SD n =&amp;gt; (2 * nat2Anat n) + 1&lt;br /&gt;
  end.&lt;br /&gt;
 &lt;br /&gt;
Example prop_nat2Anat1: (nat2Anat (SD (SD C))) = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example prop_nat2Anat2: (nat2Anat (D (SD (SD C)))) = 6.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Referencias ===&lt;br /&gt;
&lt;br /&gt;
El tema se basa en el capítulo [http://bit.ly/2zRCL6t Functional programming in Coq] del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce et als.&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=32</id>
		<title>Demostración Asistida por Ordenador con Coq</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=Demostraci%C3%B3n_Asistida_por_Ordenador_con_Coq&amp;diff=32"/>
		<updated>2018-07-27T15:40:37Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página creada con «Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de * [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] de…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
Esencialmente los apuntes son una adaptación del libro [https://softwarefoundations.cis.upenn.edu/current/lf-current Software foundations (Vol. 1: Logical foundations)] de Benjamin Peirce y otros.&lt;br /&gt;
&lt;br /&gt;
Una primera versión de estos apuntes se han usado este año en el [http://www.glc.us.es/~jalonso/SLC2018 Seminario de Lógica Computacional].&lt;br /&gt;
&lt;br /&gt;
=== Temas ===&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=31</id>
		<title>MediaWiki:Mainpage</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=31"/>
		<updated>2018-07-27T15:40:03Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Demostración Asistida por Ordenador con Coq&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=29</id>
		<title>MediaWiki:Mainpage</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=MediaWiki:Mainpage&amp;diff=29"/>
		<updated>2018-07-27T15:31:15Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DAO (demostración asistida por ordenador) con Coq&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=27</id>
		<title>Página principal</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=27"/>
		<updated>2018-07-27T15:16:51Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Apuntes de demostración asistida por ordenador con [https://coq.inria.fr/ Coq] para los cursos de&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/m-ra/ Razonamiento automático] del [http://master.cs.us.es/Máster_Universitario_en_Lógica,_Computación_e_Inteligencia_Artificial Máster Universitario en Lógica, computación e inteligencia artificial] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
* [http://www.cs.us.es/~jalonso/cursos/lmf/ Lógica matemática y fundamentos] del [http://www.us.es/estudios/grados/plan_171?p=7 Grado en Matemáticas] de la [http://www.us.es Universidad de Sevilla].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Temas&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* [[Tema 1: Programación funcional y métodos elementales de demostración en Coq]].&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=25</id>
		<title>Página principal</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=25"/>
		<updated>2018-07-27T15:09:09Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Demostración Asistida por Ordenador con Coq&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=24</id>
		<title>Página principal</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/DAOconCoq/index.php?title=P%C3%A1gina_principal&amp;diff=24"/>
		<updated>2018-07-27T15:08:17Z</updated>

		<summary type="html">&lt;p&gt;Jalonso: Página reemplazada por «Demostación Asistida por Ordenador con Coq»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Demostación Asistida por Ordenador con Coq&lt;/div&gt;</summary>
		<author><name>Jalonso</name></author>
		
	</entry>
</feed>