(** * Rel: Properties of Relations *)
(** This short (and optional) chapter develops some basic definitions and a few theorems about binary relations in Coq.  The key definitions are repeated where they are actually used (in the \CHAPV2{Smallstep} chapter of _Programming Language Foundations_), so readers who are already comfortable with these ideas can safely skim or skip this chapter.  However, relations are also a good source of exercises for developing facility with Coq's basic reasoning facilities, so it may be useful to look at this material just after the [IndProp] chapter. *)
Set Warnings "-notation-overridden,-parsing".
Require Export IndProp.
(** A binary _relation_ on a set [X] is a family of propositions parameterized by two elements of [X] -- i.e., a proposition about pairs of elements of [X].  *)
Definition relation (X: Type) := X -> X -> Prop.
(** Confusingly, the Coq standard library hijacks the generic term "relation" for this specific instance of the idea. To maintain consistency with the library, we will do the same.  So, henceforth the Coq identifier [relation] will always refer to a binary relation between some set and itself, whereas the English word "relation" can refer either to the specific Coq concept or the more general concept of a relation between any number of possibly different sets.  The context of the discussion should always make clear which is meant. *)
(** An example relation on [nat] is [le], the less-than-or-equal-to relation, which we usually write [n1 <= n2]. *)
Print le.
(* ====> Inductive le (n : nat) : nat -> Prop := le_n : n <= n | le_S : forall m : nat, n <= m -> n <= S m *)
Check le : nat -> nat -> Prop.
Check le : relation nat.
(** (Why did we write it this way instead of starting with [Inductive le : relation nat...]?  Because we wanted to put the first [nat] to the left of the [:], which makes Coq generate a somewhat nicer induction principle for reasoning about [<=].) *)
(* ################################################################# *)
(** * Basic Properties *)
(** As anyone knows who has taken an undergraduate discrete math course, there is a lot to be said about relations in general, including ways of classifying relations (as reflexive, transitive, etc.), theorems that can be proved generically about certain sorts of relations, constructions that build one relation from another, etc.  For example... *)
(* ----------------------------------------------------------------- *)
(** *** Partial Functions *)
(** A relation [R] on a set [X] is a _partial function_ if, for every [x], there is at most one [y] such that [R x y] -- i.e., [R x y1] and [R x y2] together imply [y1 = y2]. *)
Definition partial_function {X: Type} (R: relation X) :=
forall x y1 y2 : X, R x y1 -> R x y2 -> y1 = y2.
(** For example, the [next_nat] relation defined earlier is a partial function. *)
Print next_nat.
(* ====> Inductive next_nat (n : nat) : nat -> Prop := nn : next_nat n (S n) *)
Check next_nat : relation nat.

(* Specifications: *)
Theorem next_nat_partial_function :
partial_function next_nat.
(** **** Exercise: 1 star, optional  *)
Theorem le_S_n : forall n m,
(S n <= S m) -> (n <= m).