(* week-02_exercises.v *)
(* LPP 2024 - CS3234 2023-2024, Sem2 *)
(* Olivier Danvy <danvy@yale-nus.edu.sg> *)
(* Version of 25 Jan 2024 *)

(* ********** *)

(* Exercises about types: *)

Definition ta : forall A : Type, A -> A * A :=
  fun (A: Type) (a: A) => (a, a).


Definition tb : forall A B : Type, A -> B -> A * B :=
  fun (A B: Type) (a: A) (b: B) => (a, b).

Definition tc : forall A B : Type, A -> B -> B * A :=
  fun (A B: Type) (a: A) (b: B) => (b, a).


Check (tt : unit).

Definition td : forall (A : Type), (unit -> A) -> A :=
  fun (A : Type) (f: unit -> A) => f tt.

Definition te : forall A B : Type, (A -> B) -> A -> B :=
  fun (A B : Type) (f: A -> B) (a: A) => f a.

Definition tf : forall A B : Type, A -> (A -> B) -> B :=
  fun (A B : Type) (a: A) (f: A -> B)  => f a.


Definition tg : forall A B C : Type, (A -> B -> C) -> A -> B -> C :=
  fun (A B C : Type)  (f: A -> B -> C) (a: A) (b: B) => f a b.

Definition th : forall A B C : Type, (A -> B -> C) -> B -> A -> C :=
  fun (A B C : Type)  (f: A -> B -> C) (b: B) (a: A) => f a b.

Definition ti : forall A B C D : Type, (A -> C) -> (B -> D) -> A -> B -> C * D :=
  fun (A B C D : Type)  (f: A -> C) (g: B -> D) (a: A) (b: B) => (f a, g b).


Definition tj : forall A B C : Type, (A -> B) -> (B -> C) -> A -> C :=
  fun (A B C : Type)  (f: A -> B) (g: B -> C) (a: A) => (g (f a)).

Definition tk : forall A B : Type, A * B -> B * A :=
  fun (A B: Type) (p: A * B) =>
    match p with
      | (a, b) => (b, a)
      end.

Definition tl : forall A B C : Type, (A * B -> C) -> A -> B -> C :=
  fun (A B C: Type) (f: A * B -> C) (a: A) (b: B) => f (a, b).


Definition tm : forall A B C : Type, (A -> B -> C) -> A * B -> C :=
  fun (A B C: Type) (f: A -> B -> C) (p: A * B) =>
    match p with
      (a, b) => f a b
    end.


Definition tn : forall A B C : Type, A * (B * C) -> (A * B) * C :=
  fun (A B C: Type) (p: A * (B * C)) =>
    match p with
      (a, (b, c)) => ((a, b), c)
      end.

(* ********** *)

(* Exercises about propositions: *)

Proposition pa :
  forall A : Prop,
    A -> A /\ A.
Proof.
  intros A H_A.
  split.
  - exact H_A.
  - exact H_A.
Qed.

Proposition pb :
  forall A B : Prop,
    A -> B -> A /\ B.
Proof.
  intros A B H_A H_B.
  split.
  exact H_A.
  exact H_B.
Qed.

Proposition pc :
  forall A B : Prop,
    A -> B -> B /\ A.
Proof.
  intros A B H_A H_B.
  split.
  exact H_B.
  exact H_A.
Qed.

Check tt.

Proposition pd :
  forall (A : Prop),
    (unit -> A) -> A.
Proof.
  intros A H_A.
  exact (H_A tt).
Qed.

Proposition pe :
  forall A B : Prop,
    (A -> B) -> A -> B.
Proof.
  intros A B H_A_implies_B.
  exact H_A_implies_B.
  Restart.
  intros A B H_A_implies_B H_A.
  apply H_A_implies_B.
  exact H_A.
Qed.

Proposition pf :
  forall A B : Prop,
    A -> (A -> B) -> B.
Proof.
  intros A B H_A H_A_implies_B.
  exact (H_A_implies_B H_A).
Qed.

Proposition pg :
  forall A B C : Prop,
    (A -> B -> C) -> A -> B -> C.
Proof.
  intros A B C H_A_B_C.
  exact H_A_B_C.
Qed.

Proposition ph :
  forall A B C : Prop,
    (A -> B -> C) -> B -> A -> C.
Proof.
  intros A B C H_A_B_C H_B H_A.
  apply H_A_B_C.
  - exact H_A.
  - exact H_B.
  Restart.
  intros A B C H_ABC H_B H_A.
  exact (H_ABC H_A H_B).
Qed.

Proposition pi :
  forall A B C D : Prop,
    (A -> C) -> (B -> D) -> A -> B -> C /\ D.
Proof.
  intros A B C D H_AC H_BD H_A H_B.
  split.
  - exact (H_AC H_A).
  - exact (H_BD H_B).
Qed.

Proposition pj :
  forall A B C : Prop,
    (A -> B) -> (B -> C) -> A -> C.
Proof.
  intros A B C H_AB H_BC H_A.
  apply H_BC.
  apply H_AB.
  exact H_A.
Qed.

Proposition pk :
  forall A B : Prop,
    A /\ B -> B /\ A.
Proof.
  intros A B [H_A H_B].
  split.
  - exact H_B.
  - exact H_A.
Qed.

Proposition pl :
  forall A B C : Prop,
    (A /\ B -> C) -> A -> B -> C.
Proof.
  intros A B C H_ABC H_A H_B.
  apply H_ABC.
  exact (conj H_A H_B).
Qed.

Proposition pm :
  forall A B C : Prop,
    (A -> B -> C) -> A /\ B -> C.
Proof.
  intros A B C H_ABC [H_A H_B].
  exact (H_ABC H_A H_B).
Qed.

Proposition pn :
  forall A B C : Prop,
    (A /\ (B /\ C)) -> (A /\ B) /\ C.
Proof.
  intros A B C [H_A [H_B H_C]].
  split.
  - split.
    * exact H_A.
    * exact H_B.
  - exact H_C.
Qed.

(* ********** *)

(* end of week-02_exercises.v *)
