(* LEO: Uh oh -- same issue *)

Fixpoint flat_map {X Y:Type} (f:X -> list Y) (l:list X)
                   : (list Y)
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *) := [].Definition option_map {X Y : Type} (f : X -> Y) (xo : option X)
                      : option Y :=
  match xo with
    | None => None
    | Some x => Some (f x)
  end.Fixpoint fold {X Y:Type} (f: X->Y->Y) (l:list X) (b:Y)
                         : Y :=
  match l with
  | nil => b
  | h :: t => f h (fold f t b)
  end.Definition constfun {X: Type} (x: X) : nat->X :=
  fun (k:nat) => x.Definition ftrue := constfun true.Definition fold_length {X : Type} (l : list X) : nat :=
  fold (fun _ n => S n) l 0.Definition fold_map {X Y:Type} (f : X -> Y) (l : list X) : list Y
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *).(** Write down a theorem [fold_map_correct] in Coq stating that
   [fold_map] is correct, and prove it. *)
(* LEO: ... :-? *)


Definition prod_curry {X Y Z : Type}
  (f : X * Y -> Z) (x : X) (y : Y) : Z := f (x, y).(** As an exercise, define its inverse, [prod_uncurry].  Then prove
    the theorems below to show that the two are inverses. *)

Definition prod_uncurry {X Y Z : Type}
  (f : X -> Y -> Z) (p : X * Y) : Z
  (* REPLACE THIS LINE WITH ":= _your_definition_ ." *).

(* Specifications: *)
Theorem uncurry_curry : forall (X Y Z : Type) (f : X -> Y -> Z) x y, prod_curry (prod_uncurry f) x y = f x y.
Theorem curry_uncurry : forall (X Y Z : Type) (f : (X * Y) -> Z) (p : X * Y), prod_uncurry (prod_curry f) p = f p.