Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Record Monad: Type :=
  { mon:> Set -> Set
  ; bind: forall a b, mon a -> (a -> mon b) -> mon b
  ; ret: forall (a: Set), a -> mon a
  (* Laws: *)
  ; mon_lunit: forall (a b: Set) (x: a) (f: a -> mon b), bind (ret x) f = f x
      (* (return x >>= f) = (f x) *)
  ; mon_runit: forall (a: Set) (f: mon a), bind f (@ret a) = f
      (* (f >>= return) = f *)
  ; mon_assoc: forall a b c (n: mon a) (f: a -> mon b) (g: b -> mon c),
      bind (bind n f) g =
      bind n (fun x => bind (f x) g)
      (* ((n >>= f) >>= g) = n >>= (\x -> f x >>= g) *)
  }.Notation "x >>= y" := (bind x y) (at level 55).Notation "x >> y" := (bind x (fun _ => y)) (at level 30, right associativity).Notation "x <- y ; z" := (bind y (fun x : _ => z)) (at level 30, right associativity).Definition extMonad (M: Monad): Prop := forall (A B: Set) (f g: A -> M B), ext_eq f g -> forall x, bind x f = bind x g.

(* Specifications: *)
Lemma bind_eqq (M: Monad) (e: extMonad M) (A B: Set) (m n: M A) (f g: A -> M B): m = n -> ext_eq f g -> (m >>= f) = (n >>= g).