sig
  module type Basic =
    sig
      type 'a t
      val bind : 'a t -> ('-> 'b t) -> 'b t
      val return : '-> 'a t
    end
  module type Infix =
    sig
      type 'a monad
      val ( >>= ) : 'a monad -> ('-> 'b monad) -> 'b monad
      val ( >>| ) : 'a monad -> ('-> 'b) -> 'b monad
    end
  module type S =
    sig
      type 'a monad
      val ( >>= ) : 'a monad -> ('-> 'b monad) -> 'b monad
      val ( >>| ) : 'a monad -> ('-> 'b) -> 'b monad
      module Monad_infix :
        sig
          type 'a monad = 'a monad
          val ( >>= ) : 'a monad -> ('-> 'b monad) -> 'b monad
          val ( >>| ) : 'a monad -> ('-> 'b) -> 'b monad
        end
      val bind : 'a monad -> ('-> 'b monad) -> 'b monad
      val return : '-> 'a monad
      val map : 'a monad -> f:('-> 'b) -> 'b monad
      val join : 'a monad monad -> 'a monad
      val ignore : 'a monad -> unit monad
    end
  module Make :
    functor (M : Basic->
      sig
        type 'a monad = 'M.t
        val ( >>= ) : 'a monad -> ('-> 'b monad) -> 'b monad
        val ( >>| ) : 'a monad -> ('-> 'b) -> 'b monad
        module Monad_infix :
          sig
            type 'a monad = 'a monad
            val ( >>= ) : 'a monad -> ('-> 'b monad) -> 'b monad
            val ( >>| ) : 'a monad -> ('-> 'b) -> 'b monad
          end
        val bind : 'a monad -> ('-> 'b monad) -> 'b monad
        val return : '-> 'a monad
        val map : 'a monad -> f:('-> 'b) -> 'b monad
        val join : 'a monad monad -> 'a monad
        val ignore : 'a monad -> unit monad
      end
  module type Basic2 =
    sig
      type ('a, 'b) t
      val bind : ('a, 'b) t -> ('-> ('c, 'b) t) -> ('c, 'b) t
      val return : '-> ('a, 'b) t
    end
  module type Infix2 =
    sig
      type ('a, 'b) monad
      val ( >>= ) :
        ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
      val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
    end
  module type S2 =
    sig
      type ('a, 'b) monad
      val ( >>= ) :
        ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
      val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
      module Monad_infix :
        sig
          type ('a, 'b) monad = ('a, 'b) monad
          val ( >>= ) :
            ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
          val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
        end
      val bind : ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
      val return : '-> ('a, 'b) monad
      val map : ('a, 'b) monad -> f:('-> 'c) -> ('c, 'b) monad
      val join : (('a, 'b) monad, 'b) monad -> ('a, 'b) monad
      val ignore : ('a, 'b) monad -> (unit, 'b) monad
    end
  module Check_S2_refines_S :
    functor (X : S->
      sig
        type ('a, 'b) monad = 'X.monad
        val ( >>= ) :
          ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
        val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
        module Monad_infix :
          sig
            type ('a, 'b) monad = ('a, 'b) monad
            val ( >>= ) :
              ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
            val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
          end
        val bind : ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
        val return : '-> ('a, 'b) monad
        val map : ('a, 'b) monad -> f:('-> 'c) -> ('c, 'b) monad
        val join : (('a, 'b) monad, 'b) monad -> ('a, 'b) monad
        val ignore : ('a, 'b) monad -> (unit, 'b) monad
      end
  module Make2 :
    functor (M : Basic2->
      sig
        type ('a, 'b) monad = ('a, 'b) M.t
        val ( >>= ) :
          ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
        val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
        module Monad_infix :
          sig
            type ('a, 'b) monad = ('a, 'b) monad
            val ( >>= ) :
              ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
            val ( >>| ) : ('a, 'b) monad -> ('-> 'c) -> ('c, 'b) monad
          end
        val bind : ('a, 'b) monad -> ('-> ('c, 'b) monad) -> ('c, 'b) monad
        val return : '-> ('a, 'b) monad
        val map : ('a, 'b) monad -> f:('-> 'c) -> ('c, 'b) monad
        val join : (('a, 'b) monad, 'b) monad -> ('a, 'b) monad
        val ignore : ('a, 'b) monad -> (unit, 'b) monad
      end
end