Fixpoint append (q : queue data) : queue data -> queue data :=
  fun q2 : queue data =>
  match q with
  | empty => q2
  | input d q' => input data d (append q' q2)
  end.

(* Specifications: *)
Lemma append_nil1 : forall q : queue data, append (empty data) q = q.
Lemma append_nil2 : forall q : queue data, append q (empty data) = q.
Lemma input_append : forall (d : data) (q1 q2 : queue data), input data d (append q1 q2) = append (input data d q1) q2.
Lemma append_assoc : forall q1 q2 q3 : queue data, append q1 (append q2 q3) = append (append q1 q2) q3.
Lemma append_right_non_empty : forall (q1 q2 : queue data) (d : data), append q1 (input data d q2) <> empty data.
Lemma case_append_right : forall (E : Set) (x y : E) (q1 q2 : queue data) (d : data), match append q1 (input data d q2) with | empty => x | input _ _ => y end = y.
Lemma case_first_value : forall (E : Set) (x y : E) (d : data) (q : queue data), first data q = value data d -> match q with | empty => x | input _ _ => y end = y.
Lemma append_first_out : forall (q1 : queue data) (d : data), first_out data (append q1 (input data d (empty data))) = q1.
Lemma append_first : forall (q1 : queue data) (d : data), first data (append q1 (input data d (empty data))) = value data d.
Lemma first_out_input : forall (d0 d1 : data) (q : queue data), first_out data (input data d0 (input data d1 q)) = input data d0 (first_out data (input data d1 q)).
Lemma first_input : forall (d0 d1 : data) (q : queue data), first data (input data d0 (input data d1 q)) = first data (input data d1 q).
Lemma append_first_out2 : forall (d : data) (q1 : queue data), first data q1 = value data d -> append (first_out data q1) (input data d (empty data)) = q1.
Lemma inqueue_append : forall (m : data) (q1 q2 : queue data), In_queue data m q1 \/ In_queue data m q2 -> In_queue data m (append data q1 q2).
Lemma not_inqueue_append : forall (m : data) (q1 q2 : queue data), ~ In_queue data m q1 /\ ~ In_queue data m q2 -> ~ In_queue data m (append data q1 q2).
Lemma in_q_shuffle1 : forall (m1 m2 : data) (q3 q4 : queue data), In_queue data m2 (input data m1 (append data q3 q4)) -> In_queue data m2 (append data q3 (input data m1 q4)).
Lemma not_in_q_shuffle1 : forall (m1 m2 : data) (q3 q4 : queue data), ~ In_queue data m2 (input data m1 (append data q3 q4)) -> ~ In_queue data m2 (append data q3 (input data m1 q4)).
Lemma not_in_q_shuffle : forall (m1 m2 : data) (q1 q2 q3 q4 : queue data), ~ In_queue data m2 (append data q1 (input data m1 q2)) -> append data q1 q2 = append data q3 q4 -> ~ In_queue data m2 (append data q3 (input data m1 q4)).
Lemma in_q_shuffle : forall (m1 m2 : data) (q1 q2 q3 q4 : queue data), In_queue data m2 (append data q3 (input data m1 q4)) -> append data q1 q2 = append data q3 q4 -> In_queue data m2 (append data q1 (input data m1 q2)).