docs: function wrap(inner, Wrap) {
    function M(i) {
      this.inner = i;
    }
    if (Wrap === true)
      Wrap = M;
    var coerce, unpack, res = {}, ipure = inner.pure, ibind = inner.bind,
        imap = inner.map, ihandle = inner.handle, iraise = inner.raise,
        ifin = inner["finally"], ipair = inner.pair, iarr = inner.arr,
        iplus = inner.plus, ireflect = inner.reflect, ireify = inner.reify,
        irun = inner.run, ialt = inner.alt, iempty = inner.empty,
        irepeat = inner.repeat, iforPar = inner.forPar, iblock = inner.block,
        iscope = inner.scope, icoerce = inner.coerce;
    if (icoerce) {
      res.unpack = unpack = function(v) { return coerce(v).inner; };
      res.coerce = coerce = function(v) {
        if (v != null && v.constructor === Wrap)
          return v;
        return new Wrap(icoerce(v));
      };
    } else {
      res.unpack = unpack = function(v) { return v.inner; }
    }
    res.pack = function(v) { return new Wrap(v); }
    res.pure = function(v) {
      return new Wrap(ipure(v));
    };
    res.map = function(a, f) {
      return new Wrap(imap(unpack(a), f));
    };
    res.bind = function(a, f) {
      return new Wrap(ibind(unpack(a), function(v) {
        return unpack(f(v));
      }));
    };
    res.raise = function(e) {
      return new Wrap(iraise(e));
    };
    res.handle = function(a, f) {
      return new Wrap(ihandle(unpack(a), function(v) {
        return unpack(f(v));
      }));
    };
    res["finally"] = function(a, f) {
      return new Wrap(ifin(unpack(a), function() {
        return unpack(f());
      }));
    };
    res.pair = function(l, r) {
      return new Wrap(ipair(unpack(l), unpack(r)));
    };
    res.arr = function(v) {
      var i, j, len, r = [];
      for (j = 0, len = v.length; j < len; j++) {
        i = v[j];
        r.push(unpack(v));
      }
      return new Wrap(iarr(r));
    };
    res.reify = function(v) {
      return unpack(ireify(v));
    };
    res.reflect = function(v) {
      return new Wrap(ireflect(v))
    };
    res.run = function(f) {
      var args = Array.from(arguments);
      args[0] = function() {
        return unpack(f());
      };
      return irun.apply(inner, args);
    };
    res.repeat = function(f, arg) {
      return new Wrap(irepeat(function(arg) {
        return unpack(f(arg));
      }, arg));
    };
    res.forPar = function(test, body, upd, arg) {
      return new Wrap(iforPar(test, function(arg) {
        return unpack(body(arg));
      }, upd, arg));
    };
    res.block = function(f) {
      return new Wrap(iblock(function(l) {
        return unpack(f(function(arg) {
          return new Wrap(l(arg));
        }));
      }));
    };
    res.scope = function(f) {
      return new Wrap(iscope(function(l) {
        return unpack(f(function(arg) {
          return new Wrap(l(arg));
        }));
      }));
    };
    return completeMonad(res).cloneDefs();
  }