Skip to content

Commit

Permalink
exercises 2
Browse files Browse the repository at this point in the history
  • Loading branch information
benediktahrens committed Jul 29, 2024
1 parent 70c09c0 commit a4255eb
Show file tree
Hide file tree
Showing 3 changed files with 368 additions and 1 deletion.
183 changes: 183 additions & 0 deletions 2024-07-Minneapolis/2_Coq/coq_exercises.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
(** Exercise sheet for lecture 2: Fundamentals of Coq.
The goal is to replace all of the "..." by suitable Coq code
satisfying the specification below.
Written by Anders Mörtberg.
Minor modifications made by Marco Maggesi.
*)
Require Import UniMath.Foundations.Preamble.

Definition idfun : forall (A : UU), A -> A := fun (A : UU) (a : A) => a.

Definition const (A B : UU) (a : A) (b : B) : A := a.

(** * Booleans *)

Definition ifbool (A : UU) (x y : A) : bool -> A :=
bool_rect (fun _ : bool => A) x y.

Definition negbool : bool -> bool :=
ifbool bool false true.

Definition andbool (b : bool) : bool -> bool :=
ifbool (bool -> bool) (idfun bool) (const bool bool false) b.

(** Exercise: define boolean or: *)

(* Definition orbool (b : bool) : bool -> bool := ... *)

(* This should satisfy:
Eval compute in orbool true true. (* true *)
Eval compute in orbool true false. (* true *)
Eval compute in orbool false true. (* true *)
Eval compute in orbool false false. (* false *)
*)


(** * Natural numbers *)
Definition nat_rec (A : UU) (a : A) (f : nat -> A -> A) : nat -> A :=
nat_rect (fun _ : nat => A) a f.

Definition pred : nat -> nat := nat_rec nat 0 (const nat nat).

Definition even : nat -> bool := nat_rec bool true (fun _ b => negbool b).

(** Exercise: define a function odd that tests if a number is odd *)

(* Definition odd : nat -> bool := ... *)

(* This should satisfy
Eval compute in odd 24. (* false *)
Eval compute in odd 19. (* true *)
Beware of big numbers: [UniMath.Foundations.Preamble] only defines notation up to 24.
*)

(** Exercise: define a notation "myif b then x else y" for "ifbool _ x y b"
and rewrite negbool and andbool using this notation. *)

(* Notation "..." := (...) (at level 1). *)

(** Note that we cannot introduce the notation "if b then x else y" as
this is already used. *)

(* Definition negbool' (b : bool) : bool := ... *)

(* This should satisfy:
Eval compute in negbool' true. (* false *)
Eval compute in negbool' false. (* true *)
*)

(* Definition andbool' (b1 b2 : bool) : bool := ... *)

(* This should satisfy:
Eval compute in andbool true true. (* true *)
Eval compute in andbool true false. (* false *)
Eval compute in andbool false true. (* false *)
Eval compute in andbool false false. (* false *)
*)


Definition add (m : nat) : nat -> nat := nat_rec nat m (fun _ y => S y).

Definition iter (A : UU) (a : A) (f : A → A) : nat → A :=
nat_rec A a (λ _ y, f y).

(* Type space and then \hat to enter the symbol ̂. *)
Notation "f ̂ n" := (λ x, iter _ x f n) (at level 10).

Definition sub (m n : nat) : nat := pred ̂ n m.

(** Exercise: define addition using iter and S *)

(* Definition add' (m : nat) : nat → nat := ... *)

(* This should satisfy:
Eval compute in add' 4 9. (* 13 *)
*)

Definition is_zero : nat -> bool := nat_rec bool true (fun _ _ => false).

Definition eqnat (m n : nat) : bool :=
andbool (is_zero (sub m n)) (is_zero (sub n m)).

Notation "m == n" := (eqnat m n) (at level 50).

(** Exercises: define <, >, ≤, ≥ *)

(* Definition ltnat (m n : nat) : bool := ... *)

(* Notation "x < y" := (ltnat x y). *)

(* This should satisfy:
Eval compute in (2 < 3). (* true *)
Eval compute in (3 < 3). (* false *)
Eval compute in (4 < 3). (* false *)
*)

(* Definition gtnat (m n : nat) : bool := ... *)

(* Notation "x > y" := (gtnat x y). *)

(* This should satisfy:
Eval compute in (2 > 3). (* false *)
Eval compute in (3 > 3). (* false *)
Eval compute in (4 > 3). (* true *)
*)

(* Definition leqnat (m n : nat) : bool := ... *)

(* Notation "x ≤ y" := (leqnat x y) (at level 10). *)

(* This should satisfy:
Eval compute in (2 ≤ 3). (* true *)
Eval compute in (3 ≤ 3). (* true *)
Eval compute in (4 ≤ 3). (* false *)
*)

(* Definition geqnat (m n : nat) : bool := ... *)

(* Notation "x ≥ y" := (geqnat x y) (at level 10). *)

(* This should satisfy:
Eval compute in (2 ≥ 3). (* false *)
Eval compute in (3 ≥ 3). (* true *)
Eval compute in (4 ≥ 3). (* true *)
*)


(** * Coproduct and integers *)

Definition coprod_rec {A B C : UU} (f : A → C) (g : B → C) : A ⨿ B → C :=
@coprod_rect A B (λ _, C) f g.

Definition Z : UU := coprod nat nat.

Notation "⊹ x" := (inl x) (at level 20).
Notation "─ x" := (inr x) (at level 40).

Definition Z1 : Z := ⊹ 1.
Definition Z0 : Z := ⊹ 0.
Definition Zn3 : Z := ─ 2.

Definition Zcase (A : UU) (fpos : nat → A) (fneg : nat → A) : Z → A :=
coprod_rec fpos fneg.

Definition negate : Z → Z :=
Zcase Z (λ x, ifbool Z Z0 (─ pred x) (is_zero x)) (λ x, ⊹ S x).

(** Exercise (harder): define addition for Z *)

(* Definition Zadd : Z -> Z -> Z := ... *)

(* This should satisfy:
Eval compute in Zadd Z0 Z0. (* ⊹ 0 *)
Eval compute in Zadd Z1 Z1. (* ⊹ 2 *)
Eval compute in Zadd Z1 Zn3. (* ─ 1 *) (* recall that negative numbers are off-by-one *)
Eval compute in Zadd Zn3 Z1. (* ─ 1 *)
Eval compute in Zadd Zn3 Zn3. (* ─ 5 *)
Eval compute in Zadd (Zadd Zn3 Zn3) Zn3. (* ─ 8 *)
Eval compute in Zadd Z0 (negate (Zn3)). (* ⊹ 3 *)
*)
183 changes: 183 additions & 0 deletions 2024-07-Minneapolis/2_Coq/coq_solutions.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
(** Solutions to exercise sheet for lecture 2: Fundamentals of Coq.
Note that these are just suggestions for solutions and many of the
problems can have different solutions. Once you know how to prove
things in Coq you can try to prove that your solutions are equivalent
to the ones in this file.
Written by Anders Mörtberg.
Minor modifications made by Marco Maggesi.
*)
Require Import UniMath.Foundations.Preamble.

Definition idfun : forall (A : UU), A -> A := fun (A : UU) (a : A) => a.

Definition const (A B : UU) (a : A) (b : B) : A := a.

(** * Booleans *)

Definition ifbool (A : UU) (x y : A) : bool -> A :=
bool_rect (fun _ : bool => A) x y.

Definition negbool : bool -> bool :=
ifbool bool false true.

Definition andbool (b : bool) : bool -> bool :=
ifbool (bool -> bool) (idfun bool) (const bool bool false) b.

(** Exercise: define boolean or: *)

Definition orbool (b : bool) : bool -> bool :=
ifbool (bool -> bool) (const bool bool true) (idfun bool) b.

Eval compute in orbool true true. (* true *)
Eval compute in orbool true false. (* true *)
Eval compute in orbool false true. (* true *)
Eval compute in orbool false false. (* false *)

(** * Natural numbers *)

Definition nat_rec (A : UU) (a : A) (f : nat -> A -> A) : nat -> A :=
nat_rect (fun _ : nat => A) a f.

Definition pred : nat -> nat := nat_rec nat 0 (const nat nat).

Definition even : nat -> bool := nat_rec bool true (fun _ b => negbool b).

(** Exercise: define a function odd that tests if a number is odd *)
Definition odd : nat -> bool :=
nat_rec bool false (fun _ b => negbool b).

Eval compute in odd 24. (* false *)
Eval compute in odd 19. (* true *)


(** Exercise: define a notation "myif b then x else y" for "ifbool _ x y b"
and rewrite negbool and andbool using this notation. *)

Notation "'myif' b 'then' x 'else' y" := (ifbool _ x y b) (at level 1).

Definition negbool' (b : bool) : bool := myif b then false else true.

(* Check that negbool' uses ifbool by disabling printing of notations *)
(* Command palette Display All Basic Low-level Contents. *)
Print negbool'.
(* Command palette Display All Basic Low-level Contents. *)

Eval compute in negbool' true. (* false *)
Eval compute in negbool' false. (* true *)

Definition andbool' (b1 b2 : bool) : bool :=
myif b1 then b2 else false.

Eval compute in andbool true true. (* true *)
Eval compute in andbool true false. (* false *)
Eval compute in andbool false true. (* false *)
Eval compute in andbool false false. (* false *)


Definition add (m : nat) : nat -> nat := nat_rec nat m (fun _ y => S y).

Definition iter (A : UU) (a : A) (f : A → A) : nat → A :=
nat_rec A a (λ _ y, f y).

Notation "f ̂ n" := (λ x, iter _ x f n) (at level 10).

Definition sub (m n : nat) : nat := pred ̂ n m.

(** Exercise: define addition using iter and S *)
Definition add' (m : nat) : nat → nat :=
iter nat m S.

Eval compute in add' 4 9. (* 13 *)

Definition is_zero : nat -> bool := nat_rec bool true (fun _ _ => false).

Definition eqnat (m n : nat) : bool :=
andbool (is_zero (sub m n)) (is_zero (sub n m)).

Notation "m == n" := (eqnat m n) (at level 50).

(** Exercises: define <, >, ≤, ≥ *)

Definition ltnat (m n : nat) : bool := is_zero (sub (S m) n).

Notation "x < y" := (ltnat x y).

Eval compute in (2 < 3). (* true *)
Eval compute in (3 < 3). (* false *)
Eval compute in (4 < 3). (* false *)


Definition gtnat (m n : nat) : bool := n < m.

Notation "x > y" := (gtnat x y).

Eval compute in (2 > 3). (* false *)
Eval compute in (3 > 3). (* false *)
Eval compute in (4 > 3). (* true *)


Definition leqnat (m n : nat) : bool := orbool (m < n) (m == n).

Notation "x ≤ y" := (leqnat x y) (at level 10).

Eval compute in (2 ≤ 3). (* true *)
Eval compute in (3 ≤ 3). (* true *)
Eval compute in (4 ≤ 3). (* false *)


Definition geqnat (m n : nat) : bool := orbool (m > n) (m == n).

Notation "x ≥ y" := (geqnat x y) (at level 10).

Eval compute in (2 ≥ 3). (* false *)
Eval compute in (3 ≥ 3). (* true *)
Eval compute in (4 ≥ 3). (* true *)


Definition coprod_rec {A B C : UU} (f : A → C) (g : B → C) : A ⨿ B → C :=
@coprod_rect A B (λ _, C) f g.


Definition Z : UU := coprod nat nat.

Notation "⊹ x" := (inl x) (at level 20).
Notation "─ x" := (inr x) (at level 40).

Definition Z1 : Z := ⊹ 1.
Definition Z0 : Z := ⊹ 0.
Definition Zn3 : Z := ─ 2.

Definition Zcase (A : UU) (fpos : nat → A) (fneg : nat → A) : Z → A :=
coprod_rec fpos fneg.

Definition negate : Z → Z :=
Zcase Z (λ x, ifbool Z Z0 (─ pred x) (is_zero x)) (λ x, ⊹ S x).

(* Exercise (harder): define addition for Z *)

Definition Zadd : Z -> Z -> Z :=
Zcase (Z → Z)
(λ posn : nat,
Zcase Z
(λ posm : nat, ⊹ (posn + posm))
(λ negm : nat,
myif posn ≥ negm then ⊹ (posn - negm)
else (─ (negm - posn))))
(λ negn : nat,
Zcase Z
(λ posm : nat,
myif posm ≥ negn then ⊹ (posm - negn)
else (─ (negn - posm)))
(λ negm : nat, ─ (S negn + negm))).

(* This should satisfy *)
Eval compute in Zadd Z0 Z0. (* ⊹ 0 *)
Eval compute in Zadd Z1 Z1. (* ⊹ 2 *)
Eval compute in Zadd Z1 Zn3. (* ─ 1 *) (* recall that negative numbers are off-by-one *)
Eval compute in Zadd Zn3 Z1. (* ─ 1 *)
Eval compute in Zadd Zn3 Zn3. (* ─ 5 *)
Eval compute in Zadd (Zadd Zn3 Zn3) Zn3. (* ─ 8 *)
Eval compute in Zadd Z0 (negate (Zn3)). (* ⊹ 3 *)
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
### Lecture 2: Type Theory (by Niels van der Weide)
- [Lecture](2024-07-Minneapolis/2_Coq/Fundamentals_Coq.pdf)
- [Coq file](2024-07-Minneapolis/2_Coq/fundamentals_lecture.v)

- [Exercises](2024-07-Minneapolis/2_Coq/coq_exercises.v)
- [Solutions](2024-07-Minneapolis/2_Coq/coq_solutions.v)

## School on Univalent Mathematics, Cortona, 2022

Expand Down

0 comments on commit a4255eb

Please sign in to comment.