(** Homework Assignment 7#
#
##Interactive Computer Theorem
Proving#
#
CS294-9, Fall 2006#
#
UC Berkeley *)
Require Import List.
Set Implicit Arguments.
(** This assignment involves producing two strongly-specified implementations of
the same abstract data type. We'll use Coq's module system to express this
idea. I don't think you need to be an expert on ML-style module systems to do
this assignment, since I've filled in all of the module-related parts in the
template, but the curious can consult
##the
OCaml manual's tutorial##.
Feel free to copy some of the infrastructure for programming with
specifications from the ##Lecture 8
code##; you might want to add some of your own code in that spirit, too.
##Template source file##
*)
(** * Signatures *)
(** First, we define what it means to implement the dictionary ADT. *)
Module Type DICTIONARY.
(** We have some [Set] that forms the keys of dictionaries. *)
Parameter domain : Set.
(** We have the type of dictionaries, indexed by the type of data being
stored.
*)
Parameter dict : Set -> Set.
(** Look up the data associated with a given key. *)
Parameter lookup : forall (range : Set), dict range -> domain -> option range.
(** The empty dictionary *)
Parameter empty : forall (range : Set),
{D : dict range | forall (d : domain), lookup D d = None}.
(** Adding a mapping *)
Parameter add : forall (range : Set) (D : dict range) (d : domain) (r : range),
{D' : dict range | lookup D' d = Some r
/\ forall (d' : domain), d <> d' -> lookup D' d' = lookup D d'}.
End DICTIONARY.
(** This signature defines what we will require from clients who want to build
dictionaries for particular key types.
*)
Module Type DICTIONARY_PARAM.
Parameter domain : Set.
Parameter domain_eq_dec : forall (x y : domain), {x = y} + {x <> y}.
(** ...so all that we require is that equality on the key type is
decidable.
*)
End DICTIONARY_PARAM.
(** * Naive dictionaries using functions *)
(** We'll implement the dictionary ADT using the most obvious (and quite
inefficient!) representation: dictionaries will be the lookup functions
themselves.
*)
Module FuncDictionary (Param : DICTIONARY_PARAM) : DICTIONARY
with Definition domain := Param.domain.
Import Param.
Section dict.
Variable range : Set.
(** Defined as promised, dictionaries are lookup functions. *)
Definition dict := domain -> option range.
(** That makes [lookup] very convenient to write. [:-)] *)
Definition lookup : dict -> domain -> option range := fun D => D.
(** Fill in a definition for [empty]. *)
Definition empty : {D : dict | forall (d : domain), lookup D d = None}.
Admitted.
(** Fill in a definition for [add]. *)
Definition add : forall (D : dict) (d : domain) (r : range),
{D' : dict | lookup D' d = Some r
/\ forall (d' : domain), d <> d' -> lookup D' d' = lookup D d'}.
Admitted.
End dict.
Definition domain := domain.
End FuncDictionary.
(** Of course, it's always fun to see the OCaml version of your
implementation.
*)
Extraction FuncDictionary.
(** * Dictionaries using unsorted lists *)
(** Now we'll implement dictionaries using the more efficient representation of
unsorted association lists with no duplicates.
*)
Module ListDictionary (Param : DICTIONARY_PARAM) : DICTIONARY
with Definition domain := Param.domain.
Import Param.
Section dict.
Variable range : Set.
(** We start by defining an auxiliary dependent, list-like type.
The list parameter to [dict'] expresses the keys that have "already been
used" and so may not appear again.
*)
Inductive dict' : list domain -> Set :=
| Nil : forall ls,
dict' ls
| Cons : forall ls d,
~In d ls
-> range
-> dict' (d :: ls)
-> dict' ls.
(** A dictionary is just a [dict'] where no keys have already been used. *)
Definition dict := dict' nil.
(** The obvious lookup function *)
Fixpoint lookup' (ls : list domain) (D : dict' ls) (d : domain) {struct D}
: option range :=
match D with
| Nil _ => None
| Cons _ d' _ r D' =>
if domain_eq_dec d d'
then Some r
else lookup' D' d
end.
Definition lookup := lookup' (ls := nil).
(** Fill in a definition for [empty]. *)
Definition empty : {D : dict | forall (d : domain), lookup D d = None}.
Admitted.
(** Fill in a definition for [add]. You'll probably want some auxiliary
definitions for this one. *)
Definition add : forall (D : dict) (d : domain) (r : range),
{D' : dict | lookup D' d = Some r
/\ forall (d' : domain), d <> d' -> lookup D' d' = lookup D d'}.
Admitted.
End dict.
Definition domain := domain.
End ListDictionary.
Extraction ListDictionary.