(** The error monad **)
Inductive result (A:Type) :=
  | Err: result A
  | OK: A -> result A.(** The error monad **)
Inductive result (A:Type) :=
  | Err: result A
  | OK: A -> result A.(** The error monad **)
Inductive result (A:Type) :=
  | Err: result A
  | OK: A -> result 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.