From mathcomp Require Import all_ssreflect. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. (** ---------------------------------------------------------- #
# ** The Coq proof assistant and the Mathematical Components library Objective: learn the Coq system in the MC library *** Roadmap - #lesson 1#: Functions and computations - #exercise # - #lesson 2#: First steps in formal proofs - #exercise # - #lesson 3#: A few more steps in formal proofs - #exercise # - #lesson 4#: Type theory - #exercise # - #lesson 5#: Boolean reflection - #exercise # - #lesson 6#: Real proofs, finally! - #exercise # - #lesson 7#: Generic theories - #exercise # - #lesson 8#: Subtypes - #exercise # *** Teaching material - Slides and exercises #https://www-sop.inria.fr/teams/marelle/coq-18/# - Coq (#software# and #user manual#, in particular the chapter about #SSReflect#) - Mathematical Components (#software# and #book#) #


# #

(notes)
# You don't need to install Coq in order to follow this class, you just need a recent browser thanks to #jsCoq#. #
# #
# ---------------------------------------------------------- #
# ** Lesson 1: summary - functions - simple data - containers - symbolic computations - higher order functions and mathematical notations #
# ---------------------------------------------------------- #
# ** Functions Functions are built using the [fun .. => ..] syntax. The command [Check] verifies that a term is well typed. #
# *) Check (fun n => 1 + n + 1). (** #
# Notice that the type of [n] was inferred and that the whole term has type [nat -> nat], where [->] is the function space. Function application is written by writing the function on the left of the argument (eg, not as in the mathematical practice). #
# *) Check 2. Check (fun n => 1 + n + 1) 2. (** #
# Notice how [2] has a type that fits, and hence the type of the function applied to [2] is [nat]. Terms (hence functions) can be given a name using the [Definition] command. The command offers some syntactic sugar for binding the function arguments. #
# *) Definition f := (fun n => 1 + n + 1). (* Definition f n := 1 + n + 1. *) (* Definition f (n : nat) := 1 + n + 1. *) (** #
# Named terms can be printed. #
# *) Print f. (** #
# Coq is able to compute with terms, in particular one can obtain the normal form via the [Eval lazy in] command. #
# *) Eval lazy in f 2. (** #
# Notice that "computation" is made of many steps. In particular [f] has to be unfolded (delta step) and then the variable substituted for the argument (beta). #
# *) Eval lazy delta [f] in f 2. Eval lazy delta [f] beta in f 2. (** #
# Nothing but functions (and their types) are built-in in Coq. All the rest is defined, even [1], [2] and [+] are not primitive. #


# #

(notes)
# This slide corresponds to section 1.1 of #the Mathematical Components book# #
# #
# ---------------------------------------------------------- #
# ** Data types Data types can be declared using the [Inductive] command. Many of them are already available in the Coq library called [Prelude] that is automatically loaded. We hence just print them. [Inductive bool := true | false.] #
# *) Print bool. (** #
# This command declares a new type [bool] and declares how the terms (in normal form) of this type are built. Only [true] and [false] are canonical inhabitants of [bool]. To use a boolean value Coq provides the [if..then..else..] syntax. #
# *) Definition twoVtree (b : bool) := if b then 2 else 3. Eval lazy in twoVtree true. Eval lazy delta in twoVtree true. Eval lazy delta beta in twoVtree true. Eval lazy delta beta iota in twoVtree true. (** #
# We define a few boolean operators that will come in handy later on. #
# *) Definition andb (b1 b2 : bool) := if b1 then b2 else false. Definition orb (b1 b2 : bool) := if b1 then true else b2. Infix "&&" := andb. Infix "||" := orb. Check true && false || false. (** #
# The [Infix] command lets one declare infix notations. Precedence and associativity is already declared in the prelude of Coq, here we just associate the constants [andb] and [orb] to these notataions. Natural numbers are defined similarly to booleans: [Inductive nat := O | S (n : nat).] #
# *) Print nat. (** #
# Coq provides a special notation for literals, eg [3], that is just sugar for [S (S (S O))]. The Mathematical Components library adds on top of that the postfix [.+1], [.+2], .. for iterated applications of [S] to terms other than [O]. #
# *) Check 3. Check (fun x => (x + x).+2). Eval lazy in (fun x => (x + x).+2) 1. (** #
# In order to use natural numbers Coq provides two tools. An extended [if..then..else..] syntax to extract the argument of [S] and the [Fixpoint] command to define recusrsive functions. #
# *) Definition pred (n : nat) := if n is p.+1 then p else 0. Eval lazy in pred 7. (** #
# Notice that [p] is a binder. When the [if..then..else..] is evaluated, and [n] put in normal form, then if it is [S t] the variable [p] takes [t] and the then-branch is taken. Now lets define addition using recursion #
# *) Fixpoint addn n m := if n is p.+1 then (addn p m).+1 else m. Infix "+" := addn. Eval lazy in 3 + 2. (** #
# The [if..then..else..] syntax is just sugar for [match..with..end]. #
# *) Print addn. (** #
# Let's now write the equality test for natural numbers #
# *) Fixpoint eqn n m := match n, m with | 0, 0 => true | p.+1, q.+1 => eqn p q | _, _ => false end. Infix "==" := eqn. Eval lazy in 3 == 4. (** #
# Other examples are subtraction and order #
# *) Fixpoint subn m n : nat := match m, n with | p.+1, q.+1 => subn p q | _ , _ => m end. Infix "-" := subn. Eval lazy in 3 - 2. Eval lazy in 2 - 3. (* truncated *) Definition leq m n := m - n == 0. Infix "<=" := leq. Eval lazy in 4 <= 5. (** #
# #


# #

(notes)
# All the constants defined in this slide are already defined in Coq's prelude or in Mathematical Components. The main difference is that [==] is not specific to [nat] but overloaded (it works for most data types). This topic is to be developed in lesson 4. This slide corresponds to section 1.2 of #the Mathematical Components book# #
# #
# ## ---------------------------------------------------------- #
# ** Containers Containers let one aggregate data, for example to form a pair or a list. The interesting characteristic of containers is that they are polymorphic: the same container can be used to hold terms of many types. [Inductive seq (A : Type) := nil | cons (hd : A) (tl : seq A).] #
# *) Check nil. Check cons 3 [::]. (** #
# We learn that [[::]] is a notation for the empty sequence and that the type parameter [?A] is implicit. #
# *) Check 1 :: nil. Check [:: 3; 4; 5 ]. (** #
# The infix [::] notation stands for [cons]. This one is mostly used to pattern match a sequence. The notation [[:: .. ; .. ]] can be used to form sequences by separating the elements with [;]. When there are no elements what is left is [[::]] that is the empty seqeunce. And of course we can use sequences with other data types #
# *) Check [:: 3; 4; 5 ]. Check [:: true; false; true ]. (** #
# Let's now define the [size] function. #
# *) Fixpoint size A (s : seq A) := if s is _ :: tl then (size tl).+1 else 0. Eval lazy in size [:: 1; 8; 34]. (** #
# Given that the contents of containers are of an arbitrary type many common operations are parametrized by functions that are specific to the type of the contents. [[ Fixpoint map A B (f : A -> B) s := if s is e :: tl then f e :: map f tl else nil. ]] #
# *) Definition l := [:: 1; 2; 3]. Eval lazy in [seq x.+1 | x <- l]. (** #
# The #seq# library of Mathematical Components contains many combinators. Their syntax is documented in the header of the file. #


# #

(notes)
# This slide corresponds to section 1.3 of #the Mathematical Components book# #
# #
# ---------------------------------------------------------- #
# ** Symbols The section mecanism is used to describe a context under which definitions are made. Coq lets us not only define terms, but also compute with them in that context. We use this mecanism to talk about symbolic computation. #
# *) Section symbols. Variables v : nat. Eval lazy in pred v.+1 . Eval lazy in pred v . (** #
# Computation can take place in presence of variables as long as constructors can be consumed. When no more constructors are available computation is stuck. Let's not look at a very common higher order function. #
# *) Fixpoint foldr A T f (a : A) (s : seq T) := if s is x :: xs then f x (foldr f a xs) else a. (** #
# The best way to understand what [foldr] does is to postulate a variable [f] and compute. #
# *) Variable f : nat -> nat -> nat. Eval lazy in foldr f 3 [:: 1; 2 ]. (** #
# If we plug [addn] in place of [f] we obtain a term that evaluates to a number. #
# *) Eval lazy in foldr addn 3 [:: 1; 2 ]. End symbols. (** #
# #
(notes)
# This slide corresponds to sections 1.4 and 1.5 of #the Mathematical Components book# #
# #
# ---------------------------------------------------------- #
# ** Higher order functions and mathematical notations Let's try to write this formula in Coq #$$ \sum_{i=1}^n (i * 2 - 1) = n ^ 2 $$# We need a bit of infrastruture #
# *) Fixpoint iota m n := if n is u.+1 then m :: iota m.+1 u else [::]. Eval lazy in iota 0 5. (** #
# Combining [iota] and [foldr] we can get pretty close to the LaTeX source for the formula above. #
# *) Notation "\sum_ ( m <= i < n ) F" := (foldr (fun i a => F + a) 0 (iota m (n-m))). Check \sum_(1 <= x < 5) (x * 2 - 1). Eval lazy in \sum_(1 <= x < 5) (x * 2 - 1). (** #
# #


# #

(notes)
# This slide corresponds to section 1.6 of #the Mathematical Components book# #
# #
# ---------------------------------------------------------- #
# ** Lesson 1: sum up - [fun .. => ..] - [Check] - [Definition] - [Print] - [Eval lazy] - [Inductive] declarations [bool], [nat], [seq]. - [match .. with .. end] and [if .. is .. then .. else ..] - [Fixpoint] - [andb] [orb] [eqn] [leq] [addn] [subn] [size] [foldr] #
# *)