(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*          Jacques-Henri Jourdan, INRIA Paris-Rocquencourt            *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the GNU General Public License as published by  *)
(*  the Free Software Foundation, either version 2 of the License, or  *)
(*  (at your option) any later version.  This file is also distributed *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)
Require Automaton.
Module Make(Import A:Automaton.T).
(** The error monad **)
Inductive result (A:Type) :=
| Err: result A
| OK: A -> result A.
Arguments Err [A].
Arguments OK [A].
Definition bind {A B: Type} (f: result A) (g: A -> result B): result B :=
match f with
| OK x => g x
| Err => Err
end.
Definition bind2 {A B C: Type} (f: result (A * B)) (g: A -> B -> result C):
result C :=
match f with
| OK (x, y) => g x y
| Err => Err
end.
Notation "'do' X <- A ; B" := (bind A (fun X => B))
(at level 200, X ident, A at level 100, B at level 200).
Notation "'do' ( X , Y ) <- A ; B" := (bind2 A (fun X Y => B))
(at level 200, X ident, Y ident, A at level 100, B at level 200).
(** Some operations on streams **)
(** Concatenation of a list and a stream **)
Fixpoint app_str {A:Type} (l:list A) (s:Stream A) :=
match l with
| nil => s
| cons t q => Cons t (app_str q s)
end.
Infix "++" := app_str (right associativity, at level 60).

(* Specifications: *)
Lemma app_str_app_assoc {A:Type} (l1 l2:list A) (s:Stream A) :
l1 ++ (l2 ++ s) = (l1 ++ l2) ++ s.