sig
  type ('a, 'b) t
  val return : '-> ('a, 'b) Duppy.Monad.t
  val raise : '-> ('a, 'b) Duppy.Monad.t
  val bind :
    ('a, 'b) Duppy.Monad.t ->
    ('-> ('c, 'b) Duppy.Monad.t) -> ('c, 'b) Duppy.Monad.t
  val ( >>= ) :
    ('a, 'b) Duppy.Monad.t ->
    ('-> ('c, 'b) Duppy.Monad.t) -> ('c, 'b) Duppy.Monad.t
  val run :
    return:('-> unit) ->
    raise:('-> unit) -> ('a, 'b) Duppy.Monad.t -> unit
  val catch :
    ('a, 'b) Duppy.Monad.t ->
    ('-> ('a, 'c) Duppy.Monad.t) -> ('a, 'c) Duppy.Monad.t
  val ( =<< ) :
    ('-> ('a, 'c) Duppy.Monad.t) ->
    ('a, 'b) Duppy.Monad.t -> ('a, 'c) Duppy.Monad.t
  val fold_left :
    ('-> '-> ('a, 'c) Duppy.Monad.t) ->
    '-> 'b list -> ('a, 'c) Duppy.Monad.t
  val iter :
    ('-> (unit, 'b) Duppy.Monad.t) -> 'a list -> (unit, 'b) Duppy.Monad.t
  module Mutex :
    sig
      module type Mutex_control =
        sig
          type priority
          val scheduler :
            Duppy.Monad.Mutex.Mutex_control.priority Duppy.scheduler
          val priority : Duppy.Monad.Mutex.Mutex_control.priority
        end
      module type Mutex_t =
        sig
          type mutex
          module Control : Mutex_control
          val create : unit -> Duppy.Monad.Mutex.Mutex_t.mutex
          val lock :
            Duppy.Monad.Mutex.Mutex_t.mutex -> (unit, 'a) Duppy.Monad.t
          val try_lock :
            Duppy.Monad.Mutex.Mutex_t.mutex -> (bool, 'a) Duppy.Monad.t
          val unlock :
            Duppy.Monad.Mutex.Mutex_t.mutex -> (unit, 'a) Duppy.Monad.t
        end
      module Factory : functor (Control : Mutex_control-> Mutex_t
    end
  module Condition :
    sig
      module Factory :
        functor (Mutex : Mutex.Mutex_t->
          sig
            type condition
            val create : unit -> Duppy.Monad.Condition.Factory.condition
            val wait :
              Duppy.Monad.Condition.Factory.condition ->
              Mutex.mutex -> (unit, 'a) Duppy.Monad.t
            val broadcast :
              Duppy.Monad.Condition.Factory.condition ->
              (unit, 'a) Duppy.Monad.t
            val signal :
              Duppy.Monad.Condition.Factory.condition ->
              (unit, 'a) Duppy.Monad.t
          end
    end
  module type Monad_io_t =
    sig
      type socket
      module Io :
        sig
          type socket = socket
          type marker = Length of int | Split of string
          type bigarray =
              (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
              Bigarray.Array1.t
          type failure =
              Io_error
            | Unix of Unix.error * string * string
            | Unknown of exn
            | Timeout
          val read :
            ?recursive:bool ->
            ?init:string ->
            ?on_error:(string * failure -> unit) ->
            ?timeout:float ->
            priority:'->
            'a scheduler ->
            socket -> marker -> (string * string option -> unit) -> unit
          val write :
            ?exec:(unit -> unit) ->
            ?on_error:(failure -> unit) ->
            ?bigarray:bigarray ->
            ?string:Bytes.t ->
            ?timeout:float -> priority:'-> 'a scheduler -> socket -> unit
        end
      type ('a, 'b) handler = {
        scheduler : 'Duppy.scheduler;
        socket : Duppy.Monad.Monad_io_t.Io.socket;
        mutable data : string;
        on_error : Duppy.Monad.Monad_io_t.Io.failure -> 'b;
      }
      val exec :
        ?delay:float ->
        priority:'->
        ('a, 'b) Duppy.Monad.Monad_io_t.handler ->
        ('c, 'b) Duppy.Monad.t -> ('c, 'b) Duppy.Monad.t
      val delay :
        priority:'->
        ('a, 'b) Duppy.Monad.Monad_io_t.handler ->
        float -> (unit, 'b) Duppy.Monad.t
      val read :
        ?timeout:float ->
        priority:'->
        marker:Duppy.Monad.Monad_io_t.Io.marker ->
        ('a, 'b) Duppy.Monad.Monad_io_t.handler -> (string, 'b) Duppy.Monad.t
      val read_all :
        ?timeout:float ->
        priority:'->
        'Duppy.scheduler ->
        Duppy.Monad.Monad_io_t.Io.socket ->
        (string, string * Duppy.Monad.Monad_io_t.Io.failure) Duppy.Monad.t
      val write :
        ?timeout:float ->
        priority:'->
        ('a, 'b) Duppy.Monad.Monad_io_t.handler ->
        Stdlib.Bytes.t -> (unit, 'b) Duppy.Monad.t
      val write_bigarray :
        ?timeout:float ->
        priority:'->
        ('a, 'b) Duppy.Monad.Monad_io_t.handler ->
        Duppy.Monad.Monad_io_t.Io.bigarray -> (unit, 'b) Duppy.Monad.t
    end
  module MakeIo :
    functor (Io : Io_t->
      sig
        type socket = Io.socket
        module Io :
          sig
            type socket = Io.socket
            type marker = Io.marker = Length of int | Split of string
            type bigarray =
                (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
                Bigarray.Array1.t
            type failure =
              Io.failure =
                Io_error
              | Unix of Unix.error * string * string
              | Unknown of exn
              | Timeout
            val read :
              ?recursive:bool ->
              ?init:string ->
              ?on_error:(string * failure -> unit) ->
              ?timeout:float ->
              priority:'->
              'a scheduler ->
              socket -> marker -> (string * string option -> unit) -> unit
            val write :
              ?exec:(unit -> unit) ->
              ?on_error:(failure -> unit) ->
              ?bigarray:bigarray ->
              ?string:Bytes.t ->
              ?timeout:float -> priority:'-> 'a scheduler -> socket -> unit
          end
        type ('a, 'b) handler = {
          scheduler : 'a scheduler;
          socket : Io.socket;
          mutable data : string;
          on_error : Io.failure -> 'b;
        }
        val exec :
          ?delay:float ->
          priority:'-> ('a, 'b) handler -> ('c, 'b) t -> ('c, 'b) t
        val delay : priority:'-> ('a, 'b) handler -> float -> (unit, 'b) t
        val read :
          ?timeout:float ->
          priority:'->
          marker:Io.marker -> ('a, 'b) handler -> (string, 'b) t
        val read_all :
          ?timeout:float ->
          priority:'->
          'a scheduler -> Io.socket -> (string, string * Io.failure) t
        val write :
          ?timeout:float ->
          priority:'-> ('a, 'b) handler -> Bytes.t -> (unit, 'b) t
        val write_bigarray :
          ?timeout:float ->
          priority:'-> ('a, 'b) handler -> Io.bigarray -> (unit, 'b) t
      end
  module Io :
    sig
      type socket = Unix.file_descr
      module Io :
        sig
          type socket = Unix.file_descr
          type marker = Io.marker = Length of int | Split of string
          type bigarray =
              (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
              Bigarray.Array1.t
          type failure =
            Io.failure =
              Io_error
            | Unix of Unix.error * string * string
            | Unknown of exn
            | Timeout
          val read :
            ?recursive:bool ->
            ?init:string ->
            ?on_error:(string * failure -> unit) ->
            ?timeout:float ->
            priority:'->
            'a scheduler ->
            socket -> marker -> (string * string option -> unit) -> unit
          val write :
            ?exec:(unit -> unit) ->
            ?on_error:(failure -> unit) ->
            ?bigarray:bigarray ->
            ?string:Bytes.t ->
            ?timeout:float -> priority:'-> 'a scheduler -> socket -> unit
        end
      type ('a, 'b) handler = {
        scheduler : 'a scheduler;
        socket : Io.socket;
        mutable data : string;
        on_error : Io.failure -> 'b;
      }
      val exec :
        ?delay:float ->
        priority:'-> ('a, 'b) handler -> ('c, 'b) t -> ('c, 'b) t
      val delay : priority:'-> ('a, 'b) handler -> float -> (unit, 'b) t
      val read :
        ?timeout:float ->
        priority:'-> marker:Io.marker -> ('a, 'b) handler -> (string, 'b) t
      val read_all :
        ?timeout:float ->
        priority:'->
        'a scheduler -> Io.socket -> (string, string * Io.failure) t
      val write :
        ?timeout:float ->
        priority:'-> ('a, 'b) handler -> Bytes.t -> (unit, 'b) t
      val write_bigarray :
        ?timeout:float ->
        priority:'-> ('a, 'b) handler -> Io.bigarray -> (unit, 'b) t
    end
end