Fixpoint partial_stream_clen {A: Type} (h: nat -> stream A) (n: nat): nat * nat :=
match n with
| 0 => (0, 0)
| S n => let (k, m) := partial_stream_clen h n in
match h k (S m) with
| Some _ => (k, S m)
| None => (S k, 0)
end
end.
Fixpoint partial_stream_clen' {A: Type} (h: nat -> stream A) (n: nat): option (nat * nat) :=
let (k, m) := partial_stream_clen h n in
match n with
| 0 => match h k m with
| Some _ => Some (k, m)
| None => None
end
| S n => match h k m, partial_stream_clen' h n with
| Some _, Some _ => Some (k, m)
| _, _ => None
end
end.

(* Specifications: *)
Lemma partial_stream_clen'_None_iff {A: Type}: forall (h: nat -> stream A) (n: nat),
match partial_stream_clen' h n return option A with
| Some (k, m) => h k m
| None => None
end = None <->
partial_stream_clen' h n = None.
Lemma partial_stream_clen_inf0 {A: Type}: forall (h: nat -> stream A) (n: nat),
is_inf_stream (h 0) ->
partial_stream_clen h n = (0, n).
Lemma partial_stream_clen'_inf0 {A: Type}: forall (h: nat -> stream A) (n: nat),
is_inf_stream (h 0) ->
partial_stream_clen' h n = Some (0, n).
Lemma partial_stream_clen_fin0_left {A: Type}: forall (h: nat -> stream A) (n m: nat),
n < m ->
is_n_stream m (h 0) ->
partial_stream_clen h n = (0, n).
Lemma partial_stream_clen'_fin0_left {A: Type}: forall (h: nat -> stream A) (n m: nat),
n < m ->
is_n_stream m (h 0) ->
partial_stream_clen' h n = Some (0, n).
Lemma partial_stream_clen'_left {A: Type}: forall (h: nat -> stream A) (n: nat),
is_at_least_n_stream (S n) (h 0) ->
partial_stream_clen' h n = Some (0, n).
Lemma partial_stream_clen_fin0_right {A: Type}: forall (h: nat -> stream A) (n m: nat),
n > 0 ->
is_n_stream n (h 0) ->
partial_stream_clen h (m + n) =
match partial_stream_clen (fun k => h (S k)) m with
| (k1, k2) => (S k1, k2)
end.
Lemma partial_stream_clen'_fin0_right {A: Type}: forall (h: nat -> stream A) (n m: nat),
n > 0 ->
is_n_stream n (h 0) ->
partial_stream_clen' h (m + n) =
match partial_stream_clen' (fun k => h (S k)) m with
| Some (k1, k2) => Some (S k1, k2)
| None => None
end.