<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
	<id>https://www.glc.us.es/~jalonso/SLC2018/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mirmednav</id>
	<title>Seminario de Lógica Computacional (2018) - Contribuciones del usuario [es]</title>
	<link rel="self" type="application/atom+xml" href="https://www.glc.us.es/~jalonso/SLC2018/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mirmednav"/>
	<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php/Especial:Contribuciones/Mirmednav"/>
	<updated>2026-07-19T00:51:39Z</updated>
	<subtitle>Contribuciones del usuario</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_4&amp;diff=107</id>
		<title>Tema 4</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_4&amp;diff=107"/>
		<updated>2018-05-03T12:29:19Z</updated>

		<summary type="html">&lt;p&gt;Mirmednav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* T4: Polimorfismo y funciones deo orden superior en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T3_Listas.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Polimorfismo&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Listas polimórficas  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir el tipo boollist para representar las listas de&lt;br /&gt;
   booleanos con los constructores bool_nil y bool_cons tales que &lt;br /&gt;
   + bool_nil es la lista vacía y&lt;br /&gt;
   + (bool_cons x ys) es la lista obtenida añadiendo el booleano x a la&lt;br /&gt;
     lista ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive boollist : Type :=&lt;br /&gt;
  | bool_nil : boollist&lt;br /&gt;
  | bool_cons : bool -&amp;gt; boollist -&amp;gt; boollist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir el tipo (list X) para representar las listas de&lt;br /&gt;
   elementos de 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. 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. 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. 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. 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. 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. Calcular el tipo de (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. Definir la función&lt;br /&gt;
      repeat (X : Type) (x : X) (count : nat) : list X&lt;br /&gt;
   tal que (repeat X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x. Por ejemplo,&lt;br /&gt;
      repeat nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (X : Type) (x : X) (count : nat) : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0 =&amp;gt; nil X&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons X x (repeat X x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_repeat1 :&lt;br /&gt;
  repeat nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_repeat2 :&lt;br /&gt;
  repeat bool false 1 = cons bool false (nil bool).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Se definen los siguientes tipos&lt;br /&gt;
      Inductive mumble : Type :=&lt;br /&gt;
        | a : mumble&lt;br /&gt;
        | b : mumble -&amp;gt; nat -&amp;gt; mumble&lt;br /&gt;
        | c : mumble.&lt;br /&gt;
      &lt;br /&gt;
      Inductive grumble (X:Type) : Type :=&lt;br /&gt;
        | d : mumble -&amp;gt; grumble X&lt;br /&gt;
        | e : X -&amp;gt; grumble X.&lt;br /&gt;
  &lt;br /&gt;
   Decidir cuáles de los siguientes expresiones son del tipo (grumble X)&lt;br /&gt;
   para algún X:&lt;br /&gt;
      - [d (b a 5)]&lt;br /&gt;
      - [d mumble (b a 5)]&lt;br /&gt;
      - [d bool (b a 5)]&lt;br /&gt;
      - [e bool true]&lt;br /&gt;
      - [e mumble (b c 0)]&lt;br /&gt;
      - [e bool (b c 0)]&lt;br /&gt;
      - [c]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module MumbleGrumble.&lt;br /&gt;
&lt;br /&gt;
Inductive mumble : Type :=&lt;br /&gt;
  | a : mumble&lt;br /&gt;
  | b : mumble -&amp;gt; nat -&amp;gt; mumble&lt;br /&gt;
  | c : mumble.&lt;br /&gt;
&lt;br /&gt;
Inductive grumble (X:Type) : Type :=&lt;br /&gt;
  | d : mumble -&amp;gt; grumble X&lt;br /&gt;
  | e : X -&amp;gt; grumble X.&lt;br /&gt;
&lt;br /&gt;
End MumbleGrumble.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ Inferencia de tipos&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat&amp;#039; X x count : list X&lt;br /&gt;
   tal que (repeat&amp;#039; X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x. Por ejemplo,&lt;br /&gt;
      repeat&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat&amp;#039; X x count : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0        =&amp;gt; nil X&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons X x (repeat&amp;#039; X x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Calcular los tipos de repeat&amp;#039; y repeat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check repeat&amp;#039;.&lt;br /&gt;
(* ===&amp;gt; forall X : Type, X -&amp;gt; nat -&amp;gt; list X *)&lt;br /&gt;
Check repeat.&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;
   §§§ Síntesis de los tipos de los argumentos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat&amp;#039;&amp;#039; X x count : list X&lt;br /&gt;
   tal que (repeat&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;
      repeat&amp;#039;&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat&amp;#039;&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat&amp;#039;&amp;#039; X x count : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0        =&amp;gt; nil _&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons _ x (repeat&amp;#039;&amp;#039; _ x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la lista formada por los números naturales 1, 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;
   §§§ Argumentos implícitos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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;
   + repeat&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Arguments nil {X}.&lt;br /&gt;
Arguments cons {X} _ _.&lt;br /&gt;
Arguments repeat {X} x count.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la lista formada por los números naturales 1, 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. Definir la función&lt;br /&gt;
      repeat&amp;#039;&amp;#039;&amp;#039; {X : Type} (x : X) (count : nat) : list X&lt;br /&gt;
   tal que (repeat&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;
      repeat&amp;#039;&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat&amp;#039;&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat&amp;#039;&amp;#039;&amp;#039; {X : Type} (x : X) (count : nat) : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons x (repeat&amp;#039;&amp;#039;&amp;#039; x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_repeat&amp;#039;&amp;#039;&amp;#039;1 :&lt;br /&gt;
  repeat&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 test_repeat&amp;#039;&amp;#039;&amp;#039;2 :&lt;br /&gt;
  repeat false 1 = cons false nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir el tipo (list&amp;#039; {X}) para representar las listas de&lt;br /&gt;
   elementos de con los constructores nil y cons 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. Definir la función&lt;br /&gt;
      app {X : Type} (l1 l2 : list X) : (list X)&lt;br /&gt;
   tal que (app xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint app {X : Type} (l1 l2 : list X) : (list X) :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil      =&amp;gt; l2&lt;br /&gt;
  | cons h t =&amp;gt; cons h (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      rev {X:Type} (l:list X) : list X&lt;br /&gt;
   tal que (rev xs) es la inversa de xs. Por ejemplo,&lt;br /&gt;
      rev (cons 1 (cons 2 nil)) = (cons 2 (cons 1 nil)).&lt;br /&gt;
      rev (cons true nil) = cons true nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev {X:Type} (l:list X) : list X :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil      =&amp;gt; nil&lt;br /&gt;
  | cons h t =&amp;gt; app (rev t) (cons h nil)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1 :&lt;br /&gt;
  rev (cons 1 (cons 2 nil)) = (cons 2 (cons 1 nil)).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_rev2:&lt;br /&gt;
  rev (cons true nil) = cons true nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length {X : Type} (l : list X) : nat &lt;br /&gt;
   tal que (length xs) es el número de elementos de xs. Por ejemplo,&lt;br /&gt;
      length (cons 1 (cons 2 (cons 3 nil))) = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length {X : Type} (l : list X) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil       =&amp;gt; 0&lt;br /&gt;
  | cons _ l&amp;#039; =&amp;gt; S (length l&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_length1:&lt;br /&gt;
  length (cons 1 (cons 2 (cons 3 nil))) = 3.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ Explicitación de argumentos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Especificar que la siguiente definición es errónea&lt;br /&gt;
      Fail Definition mynil := nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fail Definition mynil := nil.&lt;br /&gt;
(* ==&amp;gt; Error: Cannot infer the implicit parameter X of nil. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Completar la definición anterior para obtener la lista&lt;br /&gt;
   vacía de números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mynil : list nat := nil.&lt;br /&gt;
&lt;br /&gt;
(* Alternativamente *)&lt;br /&gt;
Definition mynil&amp;#039; := @nil nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. 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 (app 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; := (app x y)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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;
   §§§ Ejercicios  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que la lista vacía es el elemento neutro por la&lt;br /&gt;
   derecha de la concatenación.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall (X:Type), forall l:list X,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof. induction l.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que la concatenación es asociativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall A (l m n:list A),&lt;br /&gt;
  l ++ m ++ n = (l ++ m) ++ n.&lt;br /&gt;
Proof.&lt;br /&gt;
   intros A l m n. induction l. &lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que la longitud de una concatenación es la suma de&lt;br /&gt;
   las longitudes de las listas (es decir, es un homomorfismo).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma app_length : forall (X:Type) (l1 l2 : list X),&lt;br /&gt;
  length (l1 ++ l2) = length l1 + length l2.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X l1 l2. induction l1.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl1. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall X (l1 l2 : list X),&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
    intros X l1 l2. induction l1.&lt;br /&gt;
  + simpl. rewrite app_nil_r. reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl1, app_assoc. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      rev (rev l) = l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall X : Type, forall l : list X,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction l.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite rev_app_distr, IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Polimorfismo de pares  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir el tipo prod (X Y) con el constructor pair tal que &lt;br /&gt;
   (pair 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;
| pair : X -&amp;gt; Y -&amp;gt; prod X Y.&lt;br /&gt;
&lt;br /&gt;
Arguments pair {X} {Y} _ _.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la abreviatura&lt;br /&gt;
      &amp;quot;( x , y )&amp;quot; para (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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. 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.&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;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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.&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;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      combine {X Y : Type} (lx : list X) (ly : list Y) : list (X*Y) &lt;br /&gt;
   tal que (combine lx ly) es la lista obtenida emparejando los&lt;br /&gt;
   elementos de lx y ly (como zip de Haskell).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint combine {X Y : Type} (lx : list X) (ly : list Y) : list (X*Y) :=&lt;br /&gt;
  match lx, ly with&lt;br /&gt;
  | []     , _       =&amp;gt; []&lt;br /&gt;
  | _      , []      =&amp;gt; []&lt;br /&gt;
  | x :: tx, y :: ty =&amp;gt; (x, y) :: (combine tx ty)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Calcular el resultado de &lt;br /&gt;
      Check combine&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Check @combine.&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Calcular el resultado de &lt;br /&gt;
      Compute (combine [1;2] [false;false;true;true]).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (combine [1;2] [false;false;true;true]).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      split {X Y : Type} (l : list (X*Y)) : (list X) * (list Y)&lt;br /&gt;
   tal que (split l) es el par de lista (lx,ly) cuyo emparejamiento es&lt;br /&gt;
   l. (La función split es como unzip de Haskell). Por ejemplo,&lt;br /&gt;
      split [(1,false);(2,false)] = ([1;2],[false;false]).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint split {X Y : Type} (l : list (X*Y)) : (list X) * (list Y) :=&lt;br /&gt;
 match l with&lt;br /&gt;
 | [] =&amp;gt; ([], [])&lt;br /&gt;
 | (x, y) :: t =&amp;gt; let s := split t in (x :: fst s, y :: snd s)&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Example test_split:&lt;br /&gt;
  split [(1,false);(2,false)] = ([1;2],[false;false]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Resultados opcionales polimórficos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir el tipo (option X) con los constructores Some y None&lt;br /&gt;
   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 option (X:Type) : Type :=&lt;br /&gt;
  | Some : X -&amp;gt; option X&lt;br /&gt;
  | None : option 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;
   Ejemplo. Definir la función&lt;br /&gt;
      nth_error {X : Type} (l : list X) (n : nat) : option X :=&lt;br /&gt;
   tal que (nth_error l n) es el n-ésimo elemento de l. Por ejemplo, &lt;br /&gt;
      nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
      nth_error [[1];[2]] 1 = Some [2].&lt;br /&gt;
      nth_error [true] 2    = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error {X : Type} (l : list X) (n : nat) : option X :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | []      =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a else nth_error l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [[1];[2]] 1 = Some [2].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [true] 2 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      hd_error {X : Type} (l : list X) : option X&lt;br /&gt;
   tal que (hd_error l) es el primer elemento de l. Por ejemplo,&lt;br /&gt;
      hd_error [1;2]     = Some 1.&lt;br /&gt;
      hd_error [[1];[2]] = Some [1].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error {X : Type} (l : list X) : option X :=&lt;br /&gt;
 match l 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 @hd_error.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [1;2] = Some 1.&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
Example test_hd_error2 : hd_error  [[1];[2]]  = Some [1].&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Funciones como datos&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Funciones de orden superior &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función &lt;br /&gt;
      doit3times {X:Type} (f:X-&amp;gt;X) (n:X) : X &lt;br /&gt;
   tal que (doit3times f) aplica 3 veces la función f. Por ejemplo,&lt;br /&gt;
      doit3times minustwo 9 = 3.&lt;br /&gt;
      doit3times negb true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition doit3times {X:Type} (f:X-&amp;gt;X) (n:X) : X :=&lt;br /&gt;
  f (f (f n)).&lt;br /&gt;
&lt;br /&gt;
Check @doit3times.&lt;br /&gt;
(* ===&amp;gt; doit3times : forall X : Type, (X -&amp;gt; X) -&amp;gt; X -&amp;gt; X *)&lt;br /&gt;
&lt;br /&gt;
Example test_doit3times: doit3times minustwo 9 = 3.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_doit3times&amp;#039;: doit3times negb true = false.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Filtrado  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      filter {X:Type} (test: X-&amp;gt;bool) (l:list X) : (list X)&lt;br /&gt;
   tal que (filter p l) es la lista de los elementos de l que verifican&lt;br /&gt;
   p. Por ejemplo,&lt;br /&gt;
      filter evenb [1;2;3;4] = [2;4].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fixpoint filter {X:Type} (test: X-&amp;gt;bool) (l:list X)&lt;br /&gt;
                : (list X) :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | []     =&amp;gt; []&lt;br /&gt;
  | h :: t =&amp;gt; if test h then h :: (filter test t)&lt;br /&gt;
                       else       filter test t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_filter1: filter evenb [1;2;3;4] = [2;4].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Definition length_is_1 {X : Type} (l : list X) : bool :=&lt;br /&gt;
  beq_nat (length l) 1.&lt;br /&gt;
&lt;br /&gt;
Example test_filter2:&lt;br /&gt;
    filter length_is_1&lt;br /&gt;
           [ [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;
   Ejemplo. Definir la función&lt;br /&gt;
      countoddmembers&amp;#039; (l:list nat) : nat &lt;br /&gt;
   tal que countoddmembers&amp;#039; l) es el número de elementos impares de&lt;br /&gt;
   l. Por ejemplo,&lt;br /&gt;
      countoddmembers&amp;#039; [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers&amp;#039; [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers&amp;#039; nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers&amp;#039; (l:list nat) : nat :=&lt;br /&gt;
  length (filter oddb l).&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers&amp;#039;1:   countoddmembers&amp;#039; [1;0;3;1;4;5] = 4.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_countoddmembers&amp;#039;2:   countoddmembers&amp;#039; [0;2;4] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_countoddmembers&amp;#039;3:   countoddmembers&amp;#039; nil = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Funciones anónimas  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      doit3times (fun n =&amp;gt; n * n) 2 = 256.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_anon_fun&amp;#039;:&lt;br /&gt;
  doit3times (fun n =&amp;gt; n * n) 2 = 256.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Calcular&lt;br /&gt;
      filter (fun l =&amp;gt; beq_nat (length l) 1)&lt;br /&gt;
             [ [1; 2]; [3]; [4]; [5;6;7]; []; [8] ]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_filter2&amp;#039;:&lt;br /&gt;
    filter (fun l =&amp;gt; beq_nat (length l) 1)&lt;br /&gt;
           [ [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. Definir la función&lt;br /&gt;
      filter_even_gt7 (l : list nat) : list nat&lt;br /&gt;
   tal que (filter_even_gt7 l) es la lista de los elemntos de l que son&lt;br /&gt;
   pares y mayores que 7. Por ejemplo,&lt;br /&gt;
      filter_even_gt7 [1;2;6;9;10;3;12;8] = [10;12;8].&lt;br /&gt;
      filter_even_gt7 [5;2;6;19;129]      = [].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition filter_even_gt7 (l : list nat) : list nat :=&lt;br /&gt;
  filter (fun x =&amp;gt; evenb x &amp;amp;&amp;amp; leb 7 x) l.&lt;br /&gt;
&lt;br /&gt;
Example test_filter_even_gt7_1 :&lt;br /&gt;
  filter_even_gt7 [1;2;6;9;10;3;12;8] = [10;12;8].&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_filter_even_gt7_2 :&lt;br /&gt;
  filter_even_gt7 [5;2;6;19;129] = [].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      partition : forall X : Type,&lt;br /&gt;
                  (X -&amp;gt; bool) -&amp;gt; list X -&amp;gt; list X * list X&lt;br /&gt;
   tal que (patition p l) es el par de lista (lx,ly) tal que lx es la&lt;br /&gt;
   lista de los elementos de l que cumplen p y ly la de las que no lo&lt;br /&gt;
   cumplen. Por ejemplo,&lt;br /&gt;
      partition oddb [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;
                     (test : X -&amp;gt; bool)&lt;br /&gt;
                     (l : list X)&lt;br /&gt;
                   : list X * list X :=&lt;br /&gt;
  (filter test l, filter (fun x =&amp;gt; negb (test x)) l).&lt;br /&gt;
&lt;br /&gt;
Example test_partition1: partition oddb [1;2;3;4;5] = ([1;3;5], [2;4]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_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;
   §§ Aplicación a todos los elementos (map)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      map {X Y:Type} (f:X-&amp;gt;Y) (l:list X) : (list Y) &lt;br /&gt;
   tal que (map f l) es la lista obtenida aplicando f a todos los&lt;br /&gt;
   elementos de l. Por ejemplo,&lt;br /&gt;
      map (fun x =&amp;gt; plus 3 x) [2;0;2] = [5;3;5].&lt;br /&gt;
      map oddb [2;1;2;5] = [false;true;false;true].&lt;br /&gt;
      map (fun n =&amp;gt; [evenb n;oddb 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) (l:list X) : (list Y) :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | []     =&amp;gt; []&lt;br /&gt;
  | h :: t =&amp;gt; (f h) :: (map f t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_map1: 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 test_map2:&lt;br /&gt;
  map oddb [2;1;2;5] = [false;true;false;true].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_map3:&lt;br /&gt;
    map (fun n =&amp;gt; [evenb n;oddb 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;
   Ejemplo. Demostrar que&lt;br /&gt;
      map f (rev l) = rev (map f l).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma map_app_distr : forall (X Y : Type) (f : X -&amp;gt; Y) (l t : list X),&lt;br /&gt;
    map f (l ++ t) = map f l ++ map f t.&lt;br /&gt;
Proof. intros X Y f l t. induction l.&lt;br /&gt;
       + reflexivity.&lt;br /&gt;
       + simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem map_rev : forall (X Y : Type) (f : X -&amp;gt; Y) (l : list X),&lt;br /&gt;
  map f (rev l) = rev (map f l).&lt;br /&gt;
Proof.&lt;br /&gt;
intros X Y f l. induction l.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite map_app_distr, IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      flat_map {X Y:Type} (f:X -&amp;gt; list Y) (l:list X) : (list Y)&lt;br /&gt;
   tal que (flat_map f l) es la concatenación de las listas obtenidas&lt;br /&gt;
   aplicando f a l. Por ejemplo,&lt;br /&gt;
      flat_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 flat_map {X Y:Type} (f:X -&amp;gt; list Y) (l:list X) &lt;br /&gt;
                   : (list Y) :=&lt;br /&gt;
   match l with&lt;br /&gt;
  | [] =&amp;gt; []&lt;br /&gt;
  | x :: t =&amp;gt; f x ++ flat_map f t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_flat_map1:&lt;br /&gt;
  flat_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. Definir la función&lt;br /&gt;
      option_map {X Y : Type} (f : X -&amp;gt; Y) (xo : option X) : option Y&lt;br /&gt;
   tal que (option_map f xo) es la aplicación de f a xo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition option_map {X Y : Type} (f : X -&amp;gt; Y) (xo : option X)&lt;br /&gt;
                      : option Y :=&lt;br /&gt;
  match xo 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;
(* =====================================================================&lt;br /&gt;
   §§ Plegados (fold)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fold {X Y:Type} (f: X-&amp;gt;Y-&amp;gt;Y) (l:list X) (b:Y) : Y&lt;br /&gt;
   tal que (fold f l b) es el plegado de l 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 andb [true;true;false;true] true = false.&lt;br /&gt;
      fold app  [[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) (l:list X) (b:Y)&lt;br /&gt;
                         : Y :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; b&lt;br /&gt;
  | h :: t =&amp;gt; f h (fold f t b)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Check (fold andb).&lt;br /&gt;
(* ===&amp;gt; fold andb : 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 andb [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 app  [[1];[];[2;3];[4]] [] = [1;2;3;4].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Funciones que construyen funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      constfun {X: Type} (x: X) : nat-&amp;gt;X&lt;br /&gt;
   tal que (constfun x) es la función que a todos los naturales le&lt;br /&gt;
   asigna el x. Por ejemplo, si se define &lt;br /&gt;
      Definition ftrue := constfun true.&lt;br /&gt;
   entonces,&lt;br /&gt;
      ftrue 0         = true.&lt;br /&gt;
      (constfun 5) 99 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition constfun {X: Type} (x: X) : nat-&amp;gt;X :=&lt;br /&gt;
  fun (k:nat) =&amp;gt; x.&lt;br /&gt;
&lt;br /&gt;
Definition ftrue := constfun true.&lt;br /&gt;
&lt;br /&gt;
Example constfun_example1 : ftrue 0 = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example constfun_example2 : (constfun 5) 99 = 5.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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. 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;
      doit3times plus3 0    = 9.&lt;br /&gt;
      doit3times (plus 3) 0 = 9.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition plus3 := plus 3.&lt;br /&gt;
&lt;br /&gt;
Example test_plus3 :    plus3 4 = 7.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_plus3&amp;#039; :   doit3times plus3 0 = 9.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_plus3&amp;#039;&amp;#039; :  doit3times (plus 3) 0 = 9.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module Exercises.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir, usando fold, la función&lt;br /&gt;
      fold_length {X : Type} (l : list X) : nat&lt;br /&gt;
   tal que (fold_length l) es la longitud de l. Por ejemplo,&lt;br /&gt;
      fold_length [4;7;0] = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Definition fold_length {X : Type} (l : list X) : nat :=&lt;br /&gt;
  fold (fun _ n =&amp;gt; S n) l 0.&lt;br /&gt;
&lt;br /&gt;
Example test_fold_length1 : fold_length [4;7;0] = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      fold_length l = length l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fold_length_correct : forall X (l : list X),&lt;br /&gt;
  fold_length l = length l.&lt;br /&gt;
Proof. intros X l. unfold fold_length. induction l.&lt;br /&gt;
       - reflexivity.&lt;br /&gt;
       - simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir, usando fold, la función&lt;br /&gt;
      fold_map {X Y:Type} (f : X -&amp;gt; Y) (l : list X) : list Y&lt;br /&gt;
   tal que (fold_map f l) es la lista obtenida aplicando f a los&lt;br /&gt;
   elementos de l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fold_map {X Y:Type} (f : X -&amp;gt; Y) (l : list X) : list Y :=&lt;br /&gt;
   fold (fun x t =&amp;gt; (f x) :: t)  l [].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que fold_map es equivalente a map.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fold_map_correct : forall (X Y : Type) (f : X -&amp;gt; Y) (l : list X),&lt;br /&gt;
     fold_map f l = map f l.&lt;br /&gt;
Proof. intros X Y f l. unfold fold_map. induction l.&lt;br /&gt;
       - reflexivity.&lt;br /&gt;
       - simpl. rewrite IHl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      prod_curry {X Y Z : Type} (f : X * Y -&amp;gt; Z) (x : X) (y : Y) : Z&lt;br /&gt;
   tal que (prod_curry f x y) es la versión curryficada de f.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prod_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;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      prod_uncurry {X Y Z : Type} (f : X -&amp;gt; Y -&amp;gt; Z) (p : X * Y) : Z&lt;br /&gt;
   tal que (prod_uncurry f p) es la versión incurryficada de f.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prod_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;
Check @prod_curry.&lt;br /&gt;
Check @prod_uncurry.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      prod_curry (prod_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;
  prod_curry (prod_uncurry f) x y = f x y.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      prod_uncurry (prod_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) (p : X * Y),&lt;br /&gt;
  prod_uncurry (prod_curry f) p = f p.&lt;br /&gt;
Proof. intros. destruct p. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      forall X n l, length l = n -&amp;gt; @nth_error X l n = None&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. 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;
&lt;br /&gt;
Module Church.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. 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. Definir la función&lt;br /&gt;
      one : nat&lt;br /&gt;
   tal que one es el número uno de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition one : 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. Definir la función&lt;br /&gt;
      two : nat&lt;br /&gt;
   tal que two es el número dos de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition two : 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. Definir la función&lt;br /&gt;
      zero : nat&lt;br /&gt;
   tal que zero es el número cero de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition zero : 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. Definir la función&lt;br /&gt;
      three : nat&lt;br /&gt;
   tal que three es el número tres de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition three : nat := @doit3times.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      succ (n : nat) : nat&lt;br /&gt;
   tal que (succ n) es el siguiente del número n de Church. Por ejemplo, &lt;br /&gt;
      succ zero = one.&lt;br /&gt;
      succ one  = two.&lt;br /&gt;
      succ two  = three.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition succ (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 succ_1 : succ zero = one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example succ_2 : succ one = two.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example succ_3 : succ two = three.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      plus (n m : nat) : nat&lt;br /&gt;
   tal que (plus n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      plus zero one             = one.&lt;br /&gt;
      plus two three            = plus three two.&lt;br /&gt;
      plus (plus two two) three = plus one (plus three three).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition plus (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 plus_1 : plus zero one = one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example plus_2 : plus two three = plus three two.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example plus_3 :&lt;br /&gt;
  plus (plus two two) three = plus one (plus three three).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      mult (n m : nat) : nat&lt;br /&gt;
   tal que (mult n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      mult one one = one.&lt;br /&gt;
      mult zero (plus three three) = zero.&lt;br /&gt;
      mult two three = plus three three.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mult (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 mult_1 : mult one one = one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example mult_2 : mult zero (plus three three) = zero.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example mult_3 : mult two three = plus three three.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      exp (n m : nat) : nat&lt;br /&gt;
   tal que (exp n m) es la potencia m-ésima de n. Por ejemplo, &lt;br /&gt;
      exp two two = plus two two.&lt;br /&gt;
      exp three two = plus (mult two (mult two two)) one.&lt;br /&gt;
      exp three zero = one.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition exp (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 exp_1 : exp two two = plus two two.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example exp_2 : exp three two = plus (mult two (mult two two)) one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example exp_3 : exp three zero = one.&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;/div&gt;</summary>
		<author><name>Mirmednav</name></author>
		
	</entry>
	<entry>
		<id>https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_4&amp;diff=106</id>
		<title>Tema 4</title>
		<link rel="alternate" type="text/html" href="https://www.glc.us.es/~jalonso/SLC2018/index.php?title=Tema_4&amp;diff=106"/>
		<updated>2018-05-03T06:39:45Z</updated>

		<summary type="html">&lt;p&gt;Mirmednav: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* T4: Polimorfismo y funciones deo orden superior en Coq *)&lt;br /&gt;
&lt;br /&gt;
Require Export T3_Listas.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Polimorfismo&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Listas polimórficas  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir el tipo boollist para representar las listas de&lt;br /&gt;
   booleanos con los constructores bool_nil y bool_cons tales que &lt;br /&gt;
   + bool_nil es la lista vacía y&lt;br /&gt;
   + (bool_cons x ys) es la lista obtenida añadiendo el booleano x a la&lt;br /&gt;
     lista ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Inductive boollist : Type :=&lt;br /&gt;
  | bool_nil : boollist&lt;br /&gt;
  | bool_cons : bool -&amp;gt; boollist -&amp;gt; boollist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir el tipo (list X) para representar las listas de&lt;br /&gt;
   elementos de 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. 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. 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. 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. 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. 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. Calcular el tipo de (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. Definir la función&lt;br /&gt;
      repeat (X : Type) (x : X) (count : nat) : list X&lt;br /&gt;
   tal que (repeat X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x. Por ejemplo,&lt;br /&gt;
      repeat nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat (X : Type) (x : X) (count : nat) : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0 =&amp;gt; nil X&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons X x (repeat X x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_repeat1 :&lt;br /&gt;
  repeat nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_repeat2 :&lt;br /&gt;
  repeat bool false 1 = cons bool false (nil bool).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Se definen los siguientes tipos&lt;br /&gt;
      Inductive mumble : Type :=&lt;br /&gt;
        | a : mumble&lt;br /&gt;
        | b : mumble -&amp;gt; nat -&amp;gt; mumble&lt;br /&gt;
        | c : mumble.&lt;br /&gt;
      &lt;br /&gt;
      Inductive grumble (X:Type) : Type :=&lt;br /&gt;
        | d : mumble -&amp;gt; grumble X&lt;br /&gt;
        | e : X -&amp;gt; grumble X.&lt;br /&gt;
  &lt;br /&gt;
   Decidir cuáles de los siguientes expresiones son del tipo (grumble X)&lt;br /&gt;
   para algún X:&lt;br /&gt;
      - [d (b a 5)]&lt;br /&gt;
      - [d mumble (b a 5)]&lt;br /&gt;
      - [d bool (b a 5)]&lt;br /&gt;
      - [e bool true]&lt;br /&gt;
      - [e mumble (b c 0)]&lt;br /&gt;
      - [e bool (b c 0)]&lt;br /&gt;
      - [c]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Module MumbleGrumble.&lt;br /&gt;
&lt;br /&gt;
Inductive mumble : Type :=&lt;br /&gt;
  | a : mumble&lt;br /&gt;
  | b : mumble -&amp;gt; nat -&amp;gt; mumble&lt;br /&gt;
  | c : mumble.&lt;br /&gt;
&lt;br /&gt;
Inductive grumble (X:Type) : Type :=&lt;br /&gt;
  | d : mumble -&amp;gt; grumble X&lt;br /&gt;
  | e : X -&amp;gt; grumble X.&lt;br /&gt;
&lt;br /&gt;
End MumbleGrumble.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ Inferencia de tipos&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat&amp;#039; X x count : list X&lt;br /&gt;
   tal que (repeat&amp;#039; X x n) es la lista obtenida repitiendo n veces el&lt;br /&gt;
   elemento x. Por ejemplo,&lt;br /&gt;
      repeat&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat&amp;#039; X x count : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0        =&amp;gt; nil X&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons X x (repeat&amp;#039; X x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Calcular los tipos de repeat&amp;#039; y repeat.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Check repeat&amp;#039;.&lt;br /&gt;
(* ===&amp;gt; forall X : Type, X -&amp;gt; nat -&amp;gt; list X *)&lt;br /&gt;
Check repeat.&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;
   §§§ Síntesis de los tipos de los argumentos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      repeat&amp;#039;&amp;#039; X x count : list X&lt;br /&gt;
   tal que (repeat&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;
      repeat&amp;#039;&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat&amp;#039;&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat&amp;#039;&amp;#039; X x count : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0        =&amp;gt; nil _&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons _ x (repeat&amp;#039;&amp;#039; _ x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la lista formada por los números naturales 1, 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;
   §§§ Argumentos implícitos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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;
   + repeat&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Arguments nil {X}.&lt;br /&gt;
Arguments cons {X} _ _.&lt;br /&gt;
Arguments repeat {X} x count.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la lista formada por los números naturales 1, 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. Definir la función&lt;br /&gt;
      repeat&amp;#039;&amp;#039;&amp;#039; {X : Type} (x : X) (count : nat) : list X&lt;br /&gt;
   tal que (repeat&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;
      repeat&amp;#039;&amp;#039; nat 4 2 = cons nat 4 (cons nat 4 (nil nat)).&lt;br /&gt;
      repeat&amp;#039;&amp;#039; bool false 1 = cons bool false (nil bool).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint repeat&amp;#039;&amp;#039;&amp;#039; {X : Type} (x : X) (count : nat) : list X :=&lt;br /&gt;
  match count with&lt;br /&gt;
  | 0        =&amp;gt; nil&lt;br /&gt;
  | S count&amp;#039; =&amp;gt; cons x (repeat&amp;#039;&amp;#039;&amp;#039; x count&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_repeat&amp;#039;&amp;#039;&amp;#039;1 :&lt;br /&gt;
  repeat&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 test_repeat&amp;#039;&amp;#039;&amp;#039;2 :&lt;br /&gt;
  repeat false 1 = cons false nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir el tipo (list&amp;#039; {X}) para representar las listas de&lt;br /&gt;
   elementos de con los constructores nil y cons 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. Definir la función&lt;br /&gt;
      app {X : Type} (l1 l2 : list X) : (list X)&lt;br /&gt;
   tal que (app xs ys) es la concatenación de xs e ys.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint app {X : Type} (l1 l2 : list X) : (list X) :=&lt;br /&gt;
  match l1 with&lt;br /&gt;
  | nil      =&amp;gt; l2&lt;br /&gt;
  | cons h t =&amp;gt; cons h (app t l2)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      rev {X:Type} (l:list X) : list X&lt;br /&gt;
   tal que (rev xs) es la inversa de xs. Por ejemplo,&lt;br /&gt;
      rev (cons 1 (cons 2 nil)) = (cons 2 (cons 1 nil)).&lt;br /&gt;
      rev (cons true nil) = cons true nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint rev {X:Type} (l:list X) : list X :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil      =&amp;gt; nil&lt;br /&gt;
  | cons h t =&amp;gt; app (rev t) (cons h nil)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_rev1 :&lt;br /&gt;
  rev (cons 1 (cons 2 nil)) = (cons 2 (cons 1 nil)).&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_rev2:&lt;br /&gt;
  rev (cons true nil) = cons true nil.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      length {X : Type} (l : list X) : nat &lt;br /&gt;
   tal que (length xs) es el número de elementos de xs. Por ejemplo,&lt;br /&gt;
      length (cons 1 (cons 2 (cons 3 nil))) = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint length {X : Type} (l : list X) : nat :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil       =&amp;gt; 0&lt;br /&gt;
  | cons _ l&amp;#039; =&amp;gt; S (length l&amp;#039;)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_length1:&lt;br /&gt;
  length (cons 1 (cons 2 (cons 3 nil))) = 3.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§§ Explicitación de argumentos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Especificar que la siguiente definición es errónea&lt;br /&gt;
      Fail Definition mynil := nil.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fail Definition mynil := nil.&lt;br /&gt;
(* ==&amp;gt; Error: Cannot infer the implicit parameter X of nil. *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Completar la definición anterior para obtener la lista&lt;br /&gt;
   vacía de números naturales.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mynil : list nat := nil.&lt;br /&gt;
&lt;br /&gt;
(* Alternativamente *)&lt;br /&gt;
Definition mynil&amp;#039; := @nil nat.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. 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 (app 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; := (app x y)&lt;br /&gt;
                     (at level 60, right associativity).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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;
   §§§ Ejercicios  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que la lista vacía es el elemento neutro por la&lt;br /&gt;
   derecha de la concatenación.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_nil_r : forall (X:Type), forall l:list X,&lt;br /&gt;
  l ++ [] = l.&lt;br /&gt;
Proof. induction l.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que la concatenación es asociativa.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem app_assoc : forall A (l m n:list A),&lt;br /&gt;
  l ++ m ++ n = (l ++ m) ++ n.&lt;br /&gt;
Proof.&lt;br /&gt;
   intros A l m n. induction l as [| x l&amp;#039; IHl]. &lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que la longitud de una concatenación es la suma de&lt;br /&gt;
   las longitudes de las listas (es decir, es un homomorfismo).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma app_length : forall (X:Type) (l1 l2 : list X),&lt;br /&gt;
  length (l1 ++ l2) = length l1 + length l2.&lt;br /&gt;
Proof.&lt;br /&gt;
  intros X l1 l2. induction l1.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl1. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_app_distr: forall X (l1 l2 : list X),&lt;br /&gt;
  rev (l1 ++ l2) = rev l2 ++ rev l1.&lt;br /&gt;
Proof.&lt;br /&gt;
    intros X l1 l2. induction l1.&lt;br /&gt;
  + simpl. rewrite app_nil_r. reflexivity.&lt;br /&gt;
  + simpl. rewrite IHl1, app_assoc. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      rev (rev l) = l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem rev_involutive : forall X : Type, forall l : list X,&lt;br /&gt;
  rev (rev l) = l.&lt;br /&gt;
Proof.&lt;br /&gt;
  induction l.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite rev_app_distr, IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
(** [] *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Polimorfismo de pares  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir el tipo prod (X Y) con el constructor pair tal que &lt;br /&gt;
   (pair 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;
| pair : X -&amp;gt; Y -&amp;gt; prod X Y.&lt;br /&gt;
&lt;br /&gt;
Arguments pair {X} {Y} _ _.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la abreviatura&lt;br /&gt;
      &amp;quot;( x , y )&amp;quot; para (pair x y).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Notation &amp;quot;( x , y )&amp;quot; := (pair x y).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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. 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.&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;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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.&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;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      combine {X Y : Type} (lx : list X) (ly : list Y) : list (X*Y) &lt;br /&gt;
   tal que (combine lx ly) es la lista obtenida emparejando los&lt;br /&gt;
   elementos de lx y ly (como zip de Haskell).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint combine {X Y : Type} (lx : list X) (ly : list Y) : list (X*Y) :=&lt;br /&gt;
  match lx, ly with&lt;br /&gt;
  | []     , _       =&amp;gt; []&lt;br /&gt;
  | _      , []      =&amp;gt; []&lt;br /&gt;
  | x :: tx, y :: ty =&amp;gt; (x, y) :: (combine tx ty)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Calcular el resultado de &lt;br /&gt;
      Check combine&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
Check @combine.&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Calcular el resultado de &lt;br /&gt;
      Compute (combine [1;2] [false;false;true;true]).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Compute (combine [1;2] [false;false;true;true]).&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      split {X Y : Type} (l : list (X*Y)) : (list X) * (list Y)&lt;br /&gt;
   tal que (split l) es el par de lista (lx,ly) cuyo emparejamiento es&lt;br /&gt;
   l. (La función split es como unzip de Haskell). Por ejemplo,&lt;br /&gt;
      split [(1,false);(2,false)] = ([1;2],[false;false]).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint split {X Y : Type} (l : list (X*Y)) : (list X) * (list Y) :=&lt;br /&gt;
 match l with&lt;br /&gt;
 | [] =&amp;gt; ([], [])&lt;br /&gt;
 | (x, y) :: t =&amp;gt; let s := split t in (x :: fst s, y :: snd s)&lt;br /&gt;
end.&lt;br /&gt;
&lt;br /&gt;
Example test_split:&lt;br /&gt;
  split [(1,false);(2,false)] = ([1;2],[false;false]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Resultados opcionales polimórficos  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir el tipo (option X) con los constructores Some y None&lt;br /&gt;
   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 option (X:Type) : Type :=&lt;br /&gt;
  | Some : X -&amp;gt; option X&lt;br /&gt;
  | None : option 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;
   Ejemplo. Definir la función&lt;br /&gt;
      nth_error {X : Type} (l : list X) (n : nat) : option X :=&lt;br /&gt;
   tal que (nth_error l n) es el n-ésimo elemento de l. Por ejemplo, &lt;br /&gt;
      nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
      nth_error [[1];[2]] 1 = Some [2].&lt;br /&gt;
      nth_error [true] 2    = None.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Fixpoint nth_error {X : Type} (l : list X) (n : nat) : option X :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | []      =&amp;gt; None&lt;br /&gt;
  | a :: l&amp;#039; =&amp;gt; if beq_nat n O then Some a else nth_error l&amp;#039; (pred n)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_nth_error1 : nth_error [4;5;6;7] 0 = Some 4.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error2 : nth_error [[1];[2]] 1 = Some [2].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_nth_error3 : nth_error [true] 2 = None.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      hd_error {X : Type} (l : list X) : option X&lt;br /&gt;
   tal que (hd_error l) es el primer elemento de l. Por ejemplo,&lt;br /&gt;
      hd_error [1;2]     = Some 1.&lt;br /&gt;
      hd_error [[1];[2]] = Some [1].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition hd_error {X : Type} (l : list X) : option X :=&lt;br /&gt;
 match l 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 @hd_error.&lt;br /&gt;
&lt;br /&gt;
Example test_hd_error1 : hd_error [1;2] = Some 1.&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
Example test_hd_error2 : hd_error  [[1];[2]]  = Some [1].&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Funciones como datos&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Funciones de orden superior &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función &lt;br /&gt;
      doit3times {X:Type} (f:X-&amp;gt;X) (n:X) : X &lt;br /&gt;
   tal que (doit3times f) aplica 3 veces la función f. Por ejemplo,&lt;br /&gt;
      doit3times minustwo 9 = 3.&lt;br /&gt;
      doit3times negb true  = false.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition doit3times {X:Type} (f:X-&amp;gt;X) (n:X) : X :=&lt;br /&gt;
  f (f (f n)).&lt;br /&gt;
&lt;br /&gt;
Check @doit3times.&lt;br /&gt;
(* ===&amp;gt; doit3times : forall X : Type, (X -&amp;gt; X) -&amp;gt; X -&amp;gt; X *)&lt;br /&gt;
&lt;br /&gt;
Example test_doit3times: doit3times minustwo 9 = 3.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_doit3times&amp;#039;: doit3times negb true = false.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Filtrado  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      filter {X:Type} (test: X-&amp;gt;bool) (l:list X) : (list X)&lt;br /&gt;
   tal que (filter p l) es la lista de los elementos de l que verifican&lt;br /&gt;
   p. Por ejemplo,&lt;br /&gt;
      filter evenb [1;2;3;4] = [2;4].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Fixpoint filter {X:Type} (test: X-&amp;gt;bool) (l:list X)&lt;br /&gt;
                : (list X) :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | []     =&amp;gt; []&lt;br /&gt;
  | h :: t =&amp;gt; if test h then h :: (filter test t)&lt;br /&gt;
                       else       filter test t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_filter1: filter evenb [1;2;3;4] = [2;4].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Definition length_is_1 {X : Type} (l : list X) : bool :=&lt;br /&gt;
  beq_nat (length l) 1.&lt;br /&gt;
&lt;br /&gt;
Example test_filter2:&lt;br /&gt;
    filter length_is_1&lt;br /&gt;
           [ [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;
   Ejemplo. Definir la función&lt;br /&gt;
      countoddmembers&amp;#039; (l:list nat) : nat &lt;br /&gt;
   tal que countoddmembers&amp;#039; l) es el número de elementos impares de&lt;br /&gt;
   l. Por ejemplo,&lt;br /&gt;
      countoddmembers&amp;#039; [1;0;3;1;4;5] = 4.&lt;br /&gt;
      countoddmembers&amp;#039; [0;2;4]       = 0.&lt;br /&gt;
      countoddmembers&amp;#039; nil           = 0.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition countoddmembers&amp;#039; (l:list nat) : nat :=&lt;br /&gt;
  length (filter oddb l).&lt;br /&gt;
&lt;br /&gt;
Example test_countoddmembers&amp;#039;1:   countoddmembers&amp;#039; [1;0;3;1;4;5] = 4.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_countoddmembers&amp;#039;2:   countoddmembers&amp;#039; [0;2;4] = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_countoddmembers&amp;#039;3:   countoddmembers&amp;#039; nil = 0.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Funciones anónimas  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      doit3times (fun n =&amp;gt; n * n) 2 = 256.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_anon_fun&amp;#039;:&lt;br /&gt;
  doit3times (fun n =&amp;gt; n * n) 2 = 256.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Calcular&lt;br /&gt;
      filter (fun l =&amp;gt; beq_nat (length l) 1)&lt;br /&gt;
             [ [1; 2]; [3]; [4]; [5;6;7]; []; [8] ]&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Example test_filter2&amp;#039;:&lt;br /&gt;
    filter (fun l =&amp;gt; beq_nat (length l) 1)&lt;br /&gt;
           [ [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. Definir la función&lt;br /&gt;
      filter_even_gt7 (l : list nat) : list nat&lt;br /&gt;
   tal que (filter_even_gt7 l) es la lista de los elemntos de l que son&lt;br /&gt;
   pares y mayores que 7. Por ejemplo,&lt;br /&gt;
      filter_even_gt7 [1;2;6;9;10;3;12;8] = [10;12;8].&lt;br /&gt;
      filter_even_gt7 [5;2;6;19;129]      = [].&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition filter_even_gt7 (l : list nat) : list nat :=&lt;br /&gt;
  filter (fun x =&amp;gt; evenb x &amp;amp;&amp;amp; leb 7 x) l.&lt;br /&gt;
&lt;br /&gt;
Example test_filter_even_gt7_1 :&lt;br /&gt;
  filter_even_gt7 [1;2;6;9;10;3;12;8] = [10;12;8].&lt;br /&gt;
 Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_filter_even_gt7_2 :&lt;br /&gt;
  filter_even_gt7 [5;2;6;19;129] = [].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      partition : forall X : Type,&lt;br /&gt;
                  (X -&amp;gt; bool) -&amp;gt; list X -&amp;gt; list X * list X&lt;br /&gt;
   tal que (patition p l) es el par de lista (lx,ly) tal que lx es la&lt;br /&gt;
   lista de los elementos de l que cumplen p y ly la de las que no lo&lt;br /&gt;
   cumplen. Por ejemplo,&lt;br /&gt;
      partition oddb [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;
                     (test : X -&amp;gt; bool)&lt;br /&gt;
                     (l : list X)&lt;br /&gt;
                   : list X * list X :=&lt;br /&gt;
  (filter test l, filter (fun x =&amp;gt; negb (test x)) l).&lt;br /&gt;
&lt;br /&gt;
Example test_partition1: partition oddb [1;2;3;4;5] = ([1;3;5], [2;4]).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
Example test_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;
   §§ Aplicación a todos los elementos (map)&lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      map {X Y:Type} (f:X-&amp;gt;Y) (l:list X) : (list Y) &lt;br /&gt;
   tal que (map f l) es la lista obtenida aplicando f a todos los&lt;br /&gt;
   elementos de l. Por ejemplo,&lt;br /&gt;
      map (fun x =&amp;gt; plus 3 x) [2;0;2] = [5;3;5].&lt;br /&gt;
      map oddb [2;1;2;5] = [false;true;false;true].&lt;br /&gt;
      map (fun n =&amp;gt; [evenb n;oddb 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) (l:list X) : (list Y) :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | []     =&amp;gt; []&lt;br /&gt;
  | h :: t =&amp;gt; (f h) :: (map f t)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_map1: 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 test_map2:&lt;br /&gt;
  map oddb [2;1;2;5] = [false;true;false;true].&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
Example test_map3:&lt;br /&gt;
    map (fun n =&amp;gt; [evenb n;oddb 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;
   Ejemplo. Demostrar que&lt;br /&gt;
      map f (rev l) = rev (map f l).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Lemma map_app_distr : forall (X Y : Type) (f : X -&amp;gt; Y) (l t : list X),&lt;br /&gt;
    map f (l ++ t) = map f l ++ map f t.&lt;br /&gt;
Proof. intros X Y f l t. induction l.&lt;br /&gt;
       + reflexivity.&lt;br /&gt;
       + simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
Theorem map_rev : forall (X Y : Type) (f : X -&amp;gt; Y) (l : list X),&lt;br /&gt;
  map f (rev l) = rev (map f l).&lt;br /&gt;
Proof.&lt;br /&gt;
intros X Y f l. induction l.&lt;br /&gt;
  + reflexivity.&lt;br /&gt;
  + simpl. rewrite map_app_distr, IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      flat_map {X Y:Type} (f:X -&amp;gt; list Y) (l:list X) : (list Y)&lt;br /&gt;
   tal que (flat_map f l) es la concatenación de las listas obtenidas&lt;br /&gt;
   aplicando f a l. Por ejemplo,&lt;br /&gt;
      flat_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 flat_map {X Y:Type} (f:X -&amp;gt; list Y) (l:list X) &lt;br /&gt;
                   : (list Y) :=&lt;br /&gt;
   match l with&lt;br /&gt;
  | [] =&amp;gt; []&lt;br /&gt;
  | x :: t =&amp;gt; f x ++ flat_map f t&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Example test_flat_map1:&lt;br /&gt;
  flat_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. Definir la función&lt;br /&gt;
      option_map {X Y : Type} (f : X -&amp;gt; Y) (xo : option X) : option Y&lt;br /&gt;
   tal que (option_map f xo) es la aplicación de f a xo.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition option_map {X Y : Type} (f : X -&amp;gt; Y) (xo : option X)&lt;br /&gt;
                      : option Y :=&lt;br /&gt;
  match xo 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;
(* =====================================================================&lt;br /&gt;
   §§ Plegados (fold)  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      fold {X Y:Type} (f: X-&amp;gt;Y-&amp;gt;Y) (l:list X) (b:Y) : Y&lt;br /&gt;
   tal que (fold f l b) es el plegado de l 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 andb [true;true;false;true] true = false.&lt;br /&gt;
      fold app  [[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) (l:list X) (b:Y)&lt;br /&gt;
                         : Y :=&lt;br /&gt;
  match l with&lt;br /&gt;
  | nil    =&amp;gt; b&lt;br /&gt;
  | h :: t =&amp;gt; f h (fold f t b)&lt;br /&gt;
  end.&lt;br /&gt;
&lt;br /&gt;
Check (fold andb).&lt;br /&gt;
(* ===&amp;gt; fold andb : 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 andb [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 app  [[1];[];[2;3];[4]] [] = [1;2;3;4].&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   §§ Funciones que construyen funciones  &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      constfun {X: Type} (x: X) : nat-&amp;gt;X&lt;br /&gt;
   tal que (constfun x) es la función que a todos los naturales le&lt;br /&gt;
   asigna el x. Por ejemplo, si se define &lt;br /&gt;
      Definition ftrue := constfun true.&lt;br /&gt;
   entonces,&lt;br /&gt;
      ftrue 0         = true.&lt;br /&gt;
      (constfun 5) 99 = 5.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition constfun {X: Type} (x: X) : nat-&amp;gt;X :=&lt;br /&gt;
  fun (k:nat) =&amp;gt; x.&lt;br /&gt;
&lt;br /&gt;
Definition ftrue := constfun true.&lt;br /&gt;
&lt;br /&gt;
Example constfun_example1 : ftrue 0 = true.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example constfun_example2 : (constfun 5) 99 = 5.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. 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. 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;
      doit3times plus3 0    = 9.&lt;br /&gt;
      doit3times (plus 3) 0 = 9.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition plus3 := plus 3.&lt;br /&gt;
&lt;br /&gt;
Example test_plus3 :    plus3 4 = 7.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_plus3&amp;#039; :   doit3times plus3 0 = 9.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
Example test_plus3&amp;#039;&amp;#039; :  doit3times (plus 3) 0 = 9.&lt;br /&gt;
Proof. reflexivity.  Qed.&lt;br /&gt;
&lt;br /&gt;
(* =====================================================================&lt;br /&gt;
   § Ejercicios &lt;br /&gt;
   ================================================================== *)&lt;br /&gt;
&lt;br /&gt;
Module Exercises.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir, usando fold, la función&lt;br /&gt;
      fold_length {X : Type} (l : list X) : nat&lt;br /&gt;
   tal que (fold_length l) es la longitud de l. Por ejemplo,&lt;br /&gt;
      fold_length [4;7;0] = 3.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
  &lt;br /&gt;
Definition fold_length {X : Type} (l : list X) : nat :=&lt;br /&gt;
  fold (fun _ n =&amp;gt; S n) l 0.&lt;br /&gt;
&lt;br /&gt;
Example test_fold_length1 : fold_length [4;7;0] = 3.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      fold_length l = length l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fold_length_correct : forall X (l : list X),&lt;br /&gt;
  fold_length l = length l.&lt;br /&gt;
Proof. intros X l. unfold fold_length. induction l.&lt;br /&gt;
       - reflexivity.&lt;br /&gt;
       - simpl. rewrite IHl. reflexivity.&lt;br /&gt;
Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir, usando fold, la función&lt;br /&gt;
      fold_map {X Y:Type} (f : X -&amp;gt; Y) (l : list X) : list Y&lt;br /&gt;
   tal que (fold_map f l) es la lista obtenida aplicando f a los&lt;br /&gt;
   elementos de l.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition fold_map {X Y:Type} (f : X -&amp;gt; Y) (l : list X) : list Y :=&lt;br /&gt;
   fold (fun x t =&amp;gt; (f x) :: t)  l [].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que fold_map es equivalente a map.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Theorem fold_map_correct : forall (X Y : Type) (f : X -&amp;gt; Y) (l : list X),&lt;br /&gt;
     fold_map f l = map f l.&lt;br /&gt;
Proof. intros X Y f l. unfold fold_map. induction l.&lt;br /&gt;
       - reflexivity.&lt;br /&gt;
       - simpl. rewrite IHl. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Definir la función&lt;br /&gt;
      prod_curry {X Y Z : Type} (f : X * Y -&amp;gt; Z) (x : X) (y : Y) : Z&lt;br /&gt;
   tal que (prod_curry f x y) es la versión curryficada de f.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prod_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;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      prod_uncurry {X Y Z : Type} (f : X -&amp;gt; Y -&amp;gt; Z) (p : X * Y) : Z&lt;br /&gt;
   tal que (prod_uncurry f p) es la versión incurryficada de f.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition prod_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;
Check @prod_curry.&lt;br /&gt;
Check @prod_uncurry.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      prod_curry (prod_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;
  prod_curry (prod_uncurry f) x y = f x y.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      prod_uncurry (prod_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) (p : X * Y),&lt;br /&gt;
  prod_uncurry (prod_curry f) p = f p.&lt;br /&gt;
Proof. intros. destruct p. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejemplo. Demostrar que&lt;br /&gt;
      forall X n l, length l = n -&amp;gt; @nth_error X l n = None&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. 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;
&lt;br /&gt;
Module Church.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. 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. Definir la función&lt;br /&gt;
      one : nat&lt;br /&gt;
   tal que one es el número uno de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition one : 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. Definir la función&lt;br /&gt;
      two : nat&lt;br /&gt;
   tal que two es el número dos de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition two : 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. Definir la función&lt;br /&gt;
      zero : nat&lt;br /&gt;
   tal que zero es el número cero de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition zero : 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. Definir la función&lt;br /&gt;
      three : nat&lt;br /&gt;
   tal que three es el número tres de Church.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition three : nat := @doit3times.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      succ (n : nat) : nat&lt;br /&gt;
   tal que (succ n) es el siguiente del número n de Church. Por ejemplo, &lt;br /&gt;
      succ zero = one.&lt;br /&gt;
      succ one  = two.&lt;br /&gt;
      succ two  = three.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition succ (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 succ_1 : succ zero = one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example succ_2 : succ one = two.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example succ_3 : succ two = three.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      plus (n m : nat) : nat&lt;br /&gt;
   tal que (plus n m) es la suma de n y m. Por ejemplo,&lt;br /&gt;
      plus zero one             = one.&lt;br /&gt;
      plus two three            = plus three two.&lt;br /&gt;
      plus (plus two two) three = plus one (plus three three).&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition plus (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 plus_1 : plus zero one = one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example plus_2 : plus two three = plus three two.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example plus_3 :&lt;br /&gt;
  plus (plus two two) three = plus one (plus three three).&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      mult (n m : nat) : nat&lt;br /&gt;
   tal que (mult n m) es el producto de n y m. Por ejemplo,&lt;br /&gt;
      mult one one = one.&lt;br /&gt;
      mult zero (plus three three) = zero.&lt;br /&gt;
      mult two three = plus three three.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition mult (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 mult_1 : mult one one = one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example mult_2 : mult zero (plus three three) = zero.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example mult_3 : mult two three = plus three three.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
(* ---------------------------------------------------------------------&lt;br /&gt;
   Ejercicio. Definir la función&lt;br /&gt;
      exp (n m : nat) : nat&lt;br /&gt;
   tal que (exp n m) es la potencia m-ésima de n. Por ejemplo, &lt;br /&gt;
      exp two two = plus two two.&lt;br /&gt;
      exp three two = plus (mult two (mult two two)) one.&lt;br /&gt;
      exp three zero = one.&lt;br /&gt;
   ------------------------------------------------------------------ *)&lt;br /&gt;
&lt;br /&gt;
Definition exp (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 exp_1 : exp two two = plus two two.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example exp_2 : exp three two = plus (mult two (mult two two)) one.&lt;br /&gt;
Proof. reflexivity. Qed.&lt;br /&gt;
&lt;br /&gt;
Example exp_3 : exp three zero = one.&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;/div&gt;</summary>
		<author><name>Mirmednav</name></author>
		
	</entry>
</feed>