Program Definition stream_app {A: Type} (h1 h2: stream A): stream A :=
fun n: nat =>
match partial_stream_len h1 n return option A with
| None => h1 n
| Some m => h2 (n - m)
end.
Next Obligation.
destruct (partial_stream_len h1 x) eqn:?H.
+ pose proof H1.
apply (partial_stream_len_mono2 h1 x y n) in H1; [| omega].
rewrite H1.
apply (stream_sound1 h2 (x - n) (y - n)); auto.
omega.
+ unfold partial_stream_len in H1.
rewrite H0 in H1.
congruence.
Qed.

(* Specifications: *)
Lemma stream_app_spec1 {A: Type}: forall (h1 h2: stream A) (m: nat),
is_at_least_n_stream (S m) h1 ->
stream_app h1 h2 m = h1 m.
Lemma stream_app_spec1' {A: Type}: forall (h1 h2: stream A) (m: nat) a,
h1 m = Some a ->
stream_app h1 h2 m = Some a.
Lemma stream_app_spec2 {A: Type}: forall (h1 h2: stream A) (n m: nat),
is_n_stream n h1 ->
stream_app h1 h2 (m + n) = h2 m.
Lemma stream_app_empty_stream {A: Type}: forall (h: stream A),
stream_app h empty_stream = h.
Lemma stream_app_fstn_skipn {A: Type}: forall (h: stream A) (n: nat),
stream_app (fstn_stream n h) (skipn_stream n h) = h.
Lemma stream_map_stream_app {A B: Type}: forall (f: A -> B) (h1 h2: stream A),
stream_map f (stream_app h1 h2) = stream_app (stream_map f h1) (stream_map f h2).
Lemma stream_app_fstn_stream {A: Type}: forall (h1 h2: stream A) (n: nat),
is_n_stream n h1 ->
fstn_stream n (stream_app h1 h2) = h1.
Lemma stream_app_skipn_stream {A: Type}: forall (h1 h2: stream A) (n: nat),
is_n_stream n h1 ->
skipn_stream n (stream_app h1 h2) = h2.