ILU3 - Partie Coq - Modules et Types Abstraits
- Auteurs:
Jean-Paul Bodeveix (resp. UE), Erik Martin-Dorel, Pierre Roux
- Date:
- L3 Info, Année 2023-2024
Supports de ce cours :
Modules en Coq et application aux TAD
1. Spécification de modules (types de modules)
Déclaration d’identificateurs.
On distingue :
des identificateurs de types
des identificateurs de constantes ou d’opérations
des identificateurs de propriétés (axiomes)
Exemple
Module Type Monoide. Parameter T : Type. (* une sorte *) Parameter un : T. (* une constante *) Parameter prod : T -> T -> T. (* une opération *) Axiom assoc : forall x y z : T, prod x (prod y z) = prod (prod x y) z. Axiom neutre_g : forall x, prod un x = x. Axiom neutre_d : forall x, prod x un = x. End Monoide.
2. Modules réalisant une spécification
Définition des identificateurs déclarés dans la spécification
Implantations possibles du monoide :
entiers avec \(0\) et \(+\)
entiers avec \(1\) et \(*\)
listes avec concaténation
type singleton
…
2. Modules réalisant une spécification
Exemple : monoide des listes avec concaténation
Require Import List. Import ListNotations. Set Implicit Arguments. Module MonoList <: Monoide. (* vérification sans masquage *) Definition T := list nat. Definition un : T := []. Definition prod (x y : T) := x ++ y.forall x y z : T, prod x (prod y z) = prod (prod x y) zapply app_assoc. Qed.forall x y z : T, prod x (prod y z) = prod (prod x y) zforall x : T, prod un x = xreflexivity. Qed.forall x : T, prod un x = xforall x : T, prod x un = xforall x : T, prod x un = xa: nat
x: list nat
IHx: prod x un = xprod (a :: x) un = a :: xa: nat
x: list nat
IHx: prod x un = xa :: prod x un = a :: xreflexivity. Qed. End MonoList.a: nat
x: list nat
IHx: prod x un = xa :: x = a :: x
3. Utilisation indépendante de l’implantation (foncteur)
Exemple : unicité de l’élément neutre
Module Use(M : Monoide).forall u : M.T, (forall x : M.T, M.prod x u = x) -> u = M.unforall u : M.T, (forall x : M.T, M.prod x u = x) -> u = M.unu: M.T
Hu: forall x : M.T, M.prod x u = xu = M.unu: M.T
Hu: forall x : M.T, M.prod x u = xu = M.prod M.un ureflexivity. Qed. End Use.u: M.T
Hu: forall x : M.T, M.prod x u = xu = u
4. Instantiation du foncteur (a.k.a. module paramétré)
Exemple
Module Inst := Use(MonoList).
Exemple autour de la structure de pile
Signature d’un TAD Pile
Ecrire la spécification du type abstrait tPile introduisant un type Elem, un type P, et les opérations habituelles sur les piles. On essaiera d’étendre au maximum le domaine des fonctions partielles (par ex. en retournant la pile vide), ou si besoin en utilisant le type option :
Inductive option {T : Type} := None | Some (valeur : T). Module Type Pile. Parameter Elem : Type. Parameter P : Type. Parameter vide : P. Parameter push : Elem -> P -> P. Parameter estVide : P -> bool. Parameter top : P -> @option Elem. Parameter pop : P -> P. (* et pas "P -> option P" : * choix de conception pour simplifier les preuves *) Axiom estVide_vide : estVide vide = true. Axiom estVide_push : forall p e, estVide (push e p) = false. Axiom top_vide : top vide = None. Axiom top_push : forall p e, top (push e p) = Some e. Axiom pop_vide : pop vide = vide. Axiom pop_push : forall p e, pop (push e p) = p. End Pile.
Implémentation du TAD Pile
Implémentez un TAD Pile d’entiers naturels, en vous appuyant sur la bibliothèque des listes.
Module Pile_Liste <: Pile. Definition Elem := nat. Definition P := list nat. Definition vide : P := []. Definition push (e : Elem) (p : P) := e :: p. Definition estVide (p : P) := match p with [] => true | _ => false end. Definition top (p : P) := match p with [] => None | x :: _ => Some x end. Definition pop (p : P) := match p with [] => [] | _ :: l => l end.estVide vide = truereflexivity. Qed.estVide vide = trueforall (p : P) (e : Elem), estVide (push e p) = falseforall (p : P) (e : Elem), estVide (push e p) = falsereflexivity. Qed.p: P
e: ElemestVide (push e p) = falsetop vide = Nonereflexivity. Qed.top vide = Noneforall (p : P) (e : Elem), top (push e p) = Some eforall (p : P) (e : Elem), top (push e p) = Some ereflexivity. Qed.p: P
e: Elemtop (push e p) = Some epop vide = videreflexivity. Qed.pop vide = videforall (p : P) (e : Elem), pop (push e p) = pforall (p : P) (e : Elem), pop (push e p) = preflexivity. Qed. End Pile_Liste.p: P
e: Elempop (push e p) = p
Autre exemple d’implémentation
Peut-on implémenter le même TAD avec des listes, mais en empilant et dépilant en queue ?
Module Pile_QListe <: Pile. Definition Elem := nat. Definition P := list nat. Definition vide : P := []. Definition push (e : Elem) (p : P) := p ++ [e]. Definition estVide (p : P) := match p with [] => true | _ => false end. Fixpoint top (p : P) := match p with [] => None | [e] => Some e | x:: l => top l end. Fixpoint pop (p : P) := match p with [] => [] | [e] => [] | x :: l => x :: pop l end.estVide vide = truereflexivity. Qed.estVide vide = trueforall (p : P) (e : Elem), estVide (push e p) = falseinduction p; simpl; auto. Qed.forall (p : P) (e : Elem), estVide (push e p) = falsetop vide = Nonereflexivity. Qed.top vide = Noneforall (p : P) (e : Elem), top (push e p) = Some einduction p; auto; destruct p; auto. Qed.forall (p : P) (e : Elem), top (push e p) = Some epop vide = videreflexivity. Qed.pop vide = videforall (p : P) (e : Elem), pop (push e p) = pforall (p : P) (e : Elem), pop (push e p) = pa: nat
p: list nat
IHp: forall e : Elem, pop (push e p) = pforall e : Elem, pop (push e (a :: p)) = a :: pintros e; rewrite <-(IHp e) at 2; auto. Qed. End Pile_QListe.a, n: nat
p: list nat
IHp: forall e : Elem, pop (push e (n :: p)) = n :: pforall e : Elem, pop (push e (a :: n :: p)) = a :: n :: p