sig
  module type Basic =
    sig
      type 'a t
      val return : '-> 'a t
      val apply : ('-> 'b) t -> 'a t -> 'b t
      val map :
        [ `Custom of 'a t -> f:('-> 'b) -> 'b t | `Define_using_apply ]
    end
  module type S =
    sig
      type 'a t
      val return : '-> 'a t
      val apply : ('-> 'b) t -> 'a t -> 'b t
      val map : 'a t -> f:('-> 'b) -> 'b t
      val map2 : 'a t -> 'b t -> f:('-> '-> 'c) -> 'c t
      val map3 : 'a t -> 'b t -> 'c t -> f:('-> '-> '-> 'd) -> 'd t
      val all : 'a t list -> 'a list t
      val both : 'a t -> 'b t -> ('a * 'b) t
      module Applicative_infix :
        sig
          val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
          val ( <* ) : 'a t -> unit t -> 'a t
          val ( *> ) : unit t -> 'a t -> 'a t
        end
      val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
      val ( <* ) : 'a t -> unit t -> 'a t
      val ( *> ) : unit t -> 'a t -> 'a t
    end
  module type Args =
    sig
      type 'a arg
      type ('f, 'r) t
      val nil : ('r, 'r) t
      val cons : 'a arg -> ('f, 'r) t -> ('-> 'f, 'r) t
      val ( @> ) : 'a arg -> ('f, 'r) t -> ('-> 'f, 'r) t
      val step : ('f1, 'r) t -> f:('f2 -> 'f1) -> ('f2, 'r) t
      val mapN : f:'-> ('f, 'r) t -> 'r arg
      val applyN : 'f arg -> ('f, 'r) t -> 'r arg
    end
  module type Basic2 =
    sig
      type ('a, 'e) t
      val return : '-> ('a, 'b) t
      val apply : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
      val map :
        [ `Custom of ('a, 'e) t -> f:('-> 'b) -> ('b, 'e) t
        | `Define_using_apply ]
    end
  module type S2 =
    sig
      type ('a, 'e) t
      val return : '-> ('a, 'b) t
      val apply : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
      val map : ('a, 'e) t -> f:('-> 'b) -> ('b, 'e) t
      val map2 : ('a, 'e) t -> ('b, 'e) t -> f:('-> '-> 'c) -> ('c, 'e) t
      val map3 :
        ('a, 'e) t ->
        ('b, 'e) t -> ('c, 'e) t -> f:('-> '-> '-> 'd) -> ('d, 'e) t
      val all : ('a, 'e) t list -> ('a list, 'e) t
      val both : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t
      module Applicative_infix :
        sig
          val ( <*> ) : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
          val ( <* ) : ('a, 'e) t -> (unit, 'e) t -> ('a, 'e) t
          val ( *> ) : (unit, 'e) t -> ('a, 'e) t -> ('a, 'e) t
        end
      val ( <*> ) : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
      val ( <* ) : ('a, 'e) t -> (unit, 'e) t -> ('a, 'e) t
      val ( *> ) : (unit, 'e) t -> ('a, 'e) t -> ('a, 'e) t
    end
  module S_to_S2 :
    functor (X : S->
      sig
        type ('a, 'e) t = 'X.t
        val return : '-> ('a, 'b) t
        val apply : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
        val map : ('a, 'e) t -> f:('-> 'b) -> ('b, 'e) t
        val map2 :
          ('a, 'e) t -> ('b, 'e) t -> f:('-> '-> 'c) -> ('c, 'e) t
        val map3 :
          ('a, 'e) t ->
          ('b, 'e) t -> ('c, 'e) t -> f:('-> '-> '-> 'd) -> ('d, 'e) t
        val all : ('a, 'e) t list -> ('a list, 'e) t
        val both : ('a, 'e) t -> ('b, 'e) t -> ('a * 'b, 'e) t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
            val ( <* ) : ('a, 'e) t -> (unit, 'e) t -> ('a, 'e) t
            val ( *> ) : (unit, 'e) t -> ('a, 'e) t -> ('a, 'e) t
          end
        val ( <*> ) : ('-> 'b, 'e) t -> ('a, 'e) t -> ('b, 'e) t
        val ( <* ) : ('a, 'e) t -> (unit, 'e) t -> ('a, 'e) t
        val ( *> ) : (unit, 'e) t -> ('a, 'e) t -> ('a, 'e) t
      end
  module S2_to_S :
    functor (X : S2->
      sig
        type 'a t = ('a, unit) X.t
        val return : '-> 'a t
        val apply : ('-> 'b) t -> 'a t -> 'b t
        val map : 'a t -> f:('-> 'b) -> 'b t
        val map2 : 'a t -> 'b t -> f:('-> '-> 'c) -> 'c t
        val map3 : 'a t -> 'b t -> 'c t -> f:('-> '-> '-> 'd) -> 'd t
        val all : 'a t list -> 'a list t
        val both : 'a t -> 'b t -> ('a * 'b) t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
            val ( <* ) : 'a t -> unit t -> 'a t
            val ( *> ) : unit t -> 'a t -> 'a t
          end
        val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
        val ( <* ) : 'a t -> unit t -> 'a t
        val ( *> ) : unit t -> 'a t -> 'a t
      end
  module type Args2 =
    sig
      type ('a, 'e) arg
      type ('f, 'r, 'e) t
      val nil : ('r, 'r, 'a) t
      val cons : ('a, 'e) arg -> ('f, 'r, 'e) t -> ('-> 'f, 'r, 'e) t
      val ( @> ) : ('a, 'e) arg -> ('f, 'r, 'e) t -> ('-> 'f, 'r, 'e) t
      val step : ('f1, 'r, 'e) t -> f:('f2 -> 'f1) -> ('f2, 'r, 'e) t
      val mapN : f:'-> ('f, 'r, 'e) t -> ('r, 'e) arg
      val applyN : ('f, 'e) arg -> ('f, 'r, 'e) t -> ('r, 'e) arg
    end
  module Args_to_Args2 :
    functor (X : Args->
      sig
        type ('a, 'e) arg = 'X.arg
        type ('f, 'r, 'e) t = ('f, 'r) X.t
        val nil : ('r, 'r, 'a) t
        val cons : ('a, 'e) arg -> ('f, 'r, 'e) t -> ('-> 'f, 'r, 'e) t
        val ( @> ) : ('a, 'e) arg -> ('f, 'r, 'e) t -> ('-> 'f, 'r, 'e) t
        val step : ('f1, 'r, 'e) t -> f:('f2 -> 'f1) -> ('f2, 'r, 'e) t
        val mapN : f:'-> ('f, 'r, 'e) t -> ('r, 'e) arg
        val applyN : ('f, 'e) arg -> ('f, 'r, 'e) t -> ('r, 'e) arg
      end
  module Make :
    functor (X : Basic->
      sig
        val return : '-> 'X.t
        val apply : ('-> 'b) X.t -> 'X.t -> 'X.t
        val map : 'X.t -> f:('-> 'b) -> 'X.t
        val map2 : 'X.t -> 'X.t -> f:('-> '-> 'c) -> 'X.t
        val map3 :
          'X.t -> 'X.t -> 'X.t -> f:('-> '-> '-> 'd) -> 'X.t
        val all : 'X.t list -> 'a list X.t
        val both : 'X.t -> 'X.t -> ('a * 'b) X.t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b) X.t -> 'X.t -> 'X.t
            val ( <* ) : 'X.t -> unit X.t -> 'X.t
            val ( *> ) : unit X.t -> 'X.t -> 'X.t
          end
        val ( <*> ) : ('-> 'b) X.t -> 'X.t -> 'X.t
        val ( <* ) : 'X.t -> unit X.t -> 'X.t
        val ( *> ) : unit X.t -> 'X.t -> 'X.t
      end
  module Make2 :
    functor (X : Basic2->
      sig
        val return : '-> ('a, 'b) X.t
        val apply : ('-> 'b, 'e) X.t -> ('a, 'e) X.t -> ('b, 'e) X.t
        val map : ('a, 'e) X.t -> f:('-> 'b) -> ('b, 'e) X.t
        val map2 :
          ('a, 'e) X.t -> ('b, 'e) X.t -> f:('-> '-> 'c) -> ('c, 'e) X.t
        val map3 :
          ('a, 'e) X.t ->
          ('b, 'e) X.t ->
          ('c, 'e) X.t -> f:('-> '-> '-> 'd) -> ('d, 'e) X.t
        val all : ('a, 'e) X.t list -> ('a list, 'e) X.t
        val both : ('a, 'e) X.t -> ('b, 'e) X.t -> ('a * 'b, 'e) X.t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b, 'e) X.t -> ('a, 'e) X.t -> ('b, 'e) X.t
            val ( <* ) : ('a, 'e) X.t -> (unit, 'e) X.t -> ('a, 'e) X.t
            val ( *> ) : (unit, 'e) X.t -> ('a, 'e) X.t -> ('a, 'e) X.t
          end
        val ( <*> ) : ('-> 'b, 'e) X.t -> ('a, 'e) X.t -> ('b, 'e) X.t
        val ( <* ) : ('a, 'e) X.t -> (unit, 'e) X.t -> ('a, 'e) X.t
        val ( *> ) : (unit, 'e) X.t -> ('a, 'e) X.t -> ('a, 'e) X.t
      end
  module Make_args :
    functor (X : S->
      sig
        type ('f, 'r) t
        val nil : ('r, 'r) t
        val cons : 'X.t -> ('f, 'r) t -> ('-> 'f, 'r) t
        val ( @> ) : 'X.t -> ('f, 'r) t -> ('-> 'f, 'r) t
        val step : ('f1, 'r) t -> f:('f2 -> 'f1) -> ('f2, 'r) t
        val mapN : f:'-> ('f, 'r) t -> 'X.t
        val applyN : 'X.t -> ('f, 'r) t -> 'X.t
      end
  module Make_args2 :
    functor (X : S2->
      sig
        type ('f, 'r, 'e) t
        val nil : ('r, 'r, 'a) t
        val cons : ('a, 'e) X.t -> ('f, 'r, 'e) t -> ('-> 'f, 'r, 'e) t
        val ( @> ) : ('a, 'e) X.t -> ('f, 'r, 'e) t -> ('-> 'f, 'r, 'e) t
        val step : ('f1, 'r, 'e) t -> f:('f2 -> 'f1) -> ('f2, 'r, 'e) t
        val mapN : f:'-> ('f, 'r, 'e) t -> ('r, 'e) X.t
        val applyN : ('f, 'e) X.t -> ('f, 'r, 'e) t -> ('r, 'e) X.t
      end
  module Of_monad :
    functor (M : Monad.S->
      sig
        val return : '-> 'M.t
        val apply : ('-> 'b) M.t -> 'M.t -> 'M.t
        val map : 'M.t -> f:('-> 'b) -> 'M.t
        val map2 : 'M.t -> 'M.t -> f:('-> '-> 'c) -> 'M.t
        val map3 :
          'M.t -> 'M.t -> 'M.t -> f:('-> '-> '-> 'd) -> 'M.t
        val all : 'M.t list -> 'a list M.t
        val both : 'M.t -> 'M.t -> ('a * 'b) M.t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b) M.t -> 'M.t -> 'M.t
            val ( <* ) : 'M.t -> unit M.t -> 'M.t
            val ( *> ) : unit M.t -> 'M.t -> 'M.t
          end
        val ( <*> ) : ('-> 'b) M.t -> 'M.t -> 'M.t
        val ( <* ) : 'M.t -> unit M.t -> 'M.t
        val ( *> ) : unit M.t -> 'M.t -> 'M.t
      end
  module Compose :
    functor (F : S) (G : S->
      sig
        type 'a t = 'F.t G.t
        val return : '-> 'a t
        val apply : ('-> 'b) t -> 'a t -> 'b t
        val map : 'a t -> f:('-> 'b) -> 'b t
        val map2 : 'a t -> 'b t -> f:('-> '-> 'c) -> 'c t
        val map3 : 'a t -> 'b t -> 'c t -> f:('-> '-> '-> 'd) -> 'd t
        val all : 'a t list -> 'a list t
        val both : 'a t -> 'b t -> ('a * 'b) t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
            val ( <* ) : 'a t -> unit t -> 'a t
            val ( *> ) : unit t -> 'a t -> 'a t
          end
        val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
        val ( <* ) : 'a t -> unit t -> 'a t
        val ( *> ) : unit t -> 'a t -> 'a t
      end
  module Pair :
    functor (F : S) (G : S->
      sig
        type 'a t = 'F.t * 'G.t
        val return : '-> 'a t
        val apply : ('-> 'b) t -> 'a t -> 'b t
        val map : 'a t -> f:('-> 'b) -> 'b t
        val map2 : 'a t -> 'b t -> f:('-> '-> 'c) -> 'c t
        val map3 : 'a t -> 'b t -> 'c t -> f:('-> '-> '-> 'd) -> 'd t
        val all : 'a t list -> 'a list t
        val both : 'a t -> 'b t -> ('a * 'b) t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
            val ( <* ) : 'a t -> unit t -> 'a t
            val ( *> ) : unit t -> 'a t -> 'a t
          end
        val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
        val ( <* ) : 'a t -> unit t -> 'a t
        val ( *> ) : unit t -> 'a t -> 'a t
      end
  module Const :
    functor
      (Monoid : sig
                  type t
                  val zero : Applicative.Const.t
                  val plus :
                    Applicative.Const.t ->
                    Applicative.Const.t -> Applicative.Const.t
                end->
      sig
        type 'a t = Monoid.t
        val return : '-> 'a t
        val apply : ('-> 'b) t -> 'a t -> 'b t
        val map : 'a t -> f:('-> 'b) -> 'b t
        val map2 : 'a t -> 'b t -> f:('-> '-> 'c) -> 'c t
        val map3 : 'a t -> 'b t -> 'c t -> f:('-> '-> '-> 'd) -> 'd t
        val all : 'a t list -> 'a list t
        val both : 'a t -> 'b t -> ('a * 'b) t
        module Applicative_infix :
          sig
            val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
            val ( <* ) : 'a t -> unit t -> 'a t
            val ( *> ) : unit t -> 'a t -> 'a t
          end
        val ( <*> ) : ('-> 'b) t -> 'a t -> 'b t
        val ( <* ) : 'a t -> unit t -> 'a t
        val ( *> ) : unit t -> 'a t -> 'a t
      end
end