import {
  getEq,
  getMonoid,
  isEmpty,
  traverse
} from "./chunk-SSXOLM6A.mjs";
import {
  bindTo,
  flap,
  let_
} from "./chunk-WKK6AYQI.mjs";
import {
  fromEquals
} from "./chunk-YQKF55QL.mjs";
import {
  apFirst,
  apS,
  apSecond
} from "./chunk-ZMCLCMOU.mjs";
import {
  bind,
  chainFirst
} from "./chunk-MDNVYLGG.mjs";
import {
  emptyRecord
} from "./chunk-WPJQNT3M.mjs";
import {
  dual,
  identity,
  pipe
} from "./chunk-ZI34HWXZ.mjs";
import {
  __export
} from "./chunk-QK4PKNB3.mjs";

// src/Tree.ts
var Tree_exports = {};
__export(Tree_exports, {
  Applicative: () => Applicative,
  Apply: () => Apply,
  Chain: () => Chain,
  Comonad: () => Comonad,
  Do: () => Do,
  Foldable: () => Foldable,
  Functor: () => Functor,
  Monad: () => Monad,
  Pointed: () => Pointed,
  Traversable: () => Traversable,
  URI: () => URI,
  ap: () => ap,
  apFirst: () => apFirst2,
  apS: () => apS2,
  apSecond: () => apSecond2,
  bind: () => bind2,
  bindTo: () => bindTo2,
  chain: () => chain,
  chainFirst: () => chainFirst2,
  drawForest: () => drawForest,
  drawTree: () => drawTree,
  duplicate: () => duplicate,
  elem: () => elem,
  exists: () => exists,
  extend: () => extend,
  extract: () => extract,
  flap: () => flap2,
  flatMap: () => flatMap,
  flatten: () => flatten,
  fold: () => fold,
  foldMap: () => foldMap,
  getEq: () => getEq2,
  getShow: () => getShow,
  let: () => let_2,
  make: () => make,
  map: () => map,
  of: () => of,
  reduce: () => reduce,
  reduceRight: () => reduceRight,
  sequence: () => sequence,
  traverse: () => traverse2,
  tree: () => tree,
  unfoldForest: () => unfoldForest,
  unfoldForestM: () => unfoldForestM,
  unfoldTree: () => unfoldTree,
  unfoldTreeM: () => unfoldTreeM
});
function make(value, forest = []) {
  return {
    value,
    forest
  };
}
function getShow(S) {
  const show = (t) => {
    return isEmpty(t.forest) ? `make(${S.show(t.value)})` : `make(${S.show(t.value)}, [${t.forest.map(show).join(", ")}])`;
  };
  return {
    show
  };
}
function getEq2(E) {
  let SA;
  const R = fromEquals((x, y) => E.equals(x.value, y.value) && SA.equals(x.forest, y.forest));
  SA = getEq(R);
  return R;
}
var draw = (indentation, forest) => {
  let r = "";
  const len = forest.length;
  let tree2;
  for (let i = 0; i < len; i++) {
    tree2 = forest[i];
    const isLast = i === len - 1;
    r += indentation + (isLast ? "\u2514" : "\u251C") + "\u2500 " + tree2.value;
    r += draw(indentation + (len > 1 && !isLast ? "\u2502  " : "   "), tree2.forest);
  }
  return r;
};
function drawForest(forest) {
  return draw("\n", forest);
}
function drawTree(tree2) {
  return tree2.value + drawForest(tree2.forest);
}
function unfoldTree(b, f) {
  const [a, bs] = f(b);
  return { value: a, forest: unfoldForest(bs, f) };
}
function unfoldForest(bs, f) {
  return bs.map((b) => unfoldTree(b, f));
}
function unfoldTreeM(M) {
  const unfoldForestMM = unfoldForestM(M);
  return (b, f) => M.chain(f(b), ([a, bs]) => M.map(unfoldForestMM(bs, f), (ts) => ({ value: a, forest: ts })));
}
function unfoldForestM(M) {
  const traverseM = traverse(M);
  return (bs, f) => pipe(
    bs,
    traverseM((b) => unfoldTreeM(M)(b, f))
  );
}
function fold(f) {
  const go = (tree2) => f(tree2.value, tree2.forest.map(go));
  return go;
}
var _map = (fa, f) => pipe(fa, map(f));
var _ap = (fab, fa) => flatMap(fab, (f) => pipe(fa, map(f)));
var _reduce = (fa, b, f) => pipe(fa, reduce(b, f));
var _foldMap = (M) => {
  const foldMapM = foldMap(M);
  return (fa, f) => pipe(fa, foldMapM(f));
};
var _reduceRight = (fa, b, f) => pipe(fa, reduceRight(b, f));
var _extend = (wa, f) => pipe(wa, extend(f));
var _traverse = (F) => {
  const traverseF = traverse2(F);
  return (ta, f) => pipe(ta, traverseF(f));
};
var ap = (fa) => (fab) => _ap(fab, fa);
var flatMap = /* @__PURE__ */ dual(2, (ma, f) => {
  const { value, forest } = f(ma.value);
  const concat = getMonoid().concat;
  return {
    value,
    forest: concat(forest, ma.forest.map(flatMap(f)))
  };
});
var extend = (f) => (wa) => ({
  value: f(wa),
  forest: wa.forest.map(extend(f))
});
var duplicate = /* @__PURE__ */ extend(identity);
var flatten = /* @__PURE__ */ flatMap(identity);
var map = (f) => (fa) => ({
  value: f(fa.value),
  forest: fa.forest.map(map(f))
});
var reduce = (b, f) => (fa) => {
  let r = f(b, fa.value);
  const len = fa.forest.length;
  for (let i = 0; i < len; i++) {
    r = pipe(fa.forest[i], reduce(r, f));
  }
  return r;
};
var foldMap = (M) => (f) => reduce(M.empty, (acc, a) => M.concat(acc, f(a)));
var reduceRight = (b, f) => (fa) => {
  let r = b;
  const len = fa.forest.length;
  for (let i = len - 1; i >= 0; i--) {
    r = pipe(fa.forest[i], reduceRight(r, f));
  }
  return f(fa.value, r);
};
var extract = (wa) => wa.value;
var traverse2 = (F) => {
  const traverseF = traverse(F);
  const out = (f) => (ta) => F.ap(
    F.map(f(ta.value), (value) => (forest) => ({
      value,
      forest
    })),
    pipe(ta.forest, traverseF(out(f)))
  );
  return out;
};
var sequence = (F) => traverse2(F)(identity);
var of = (a) => make(a);
var URI = "Tree";
var Functor = {
  URI,
  map: _map
};
var flap2 = /* @__PURE__ */ flap(Functor);
var Pointed = {
  URI,
  of
};
var Apply = {
  URI,
  map: _map,
  ap: _ap
};
var apFirst2 = /* @__PURE__ */ apFirst(Apply);
var apSecond2 = /* @__PURE__ */ apSecond(Apply);
var Applicative = {
  URI,
  map: _map,
  ap: _ap,
  of
};
var Chain = {
  URI,
  map: _map,
  ap: _ap,
  chain: flatMap
};
var Monad = {
  URI,
  map: _map,
  ap: _ap,
  of,
  chain: flatMap
};
var chainFirst2 = /* @__PURE__ */ chainFirst(Chain);
var Foldable = {
  URI,
  reduce: _reduce,
  foldMap: _foldMap,
  reduceRight: _reduceRight
};
var Traversable = {
  URI,
  map: _map,
  reduce: _reduce,
  foldMap: _foldMap,
  reduceRight: _reduceRight,
  traverse: _traverse,
  sequence
};
var Comonad = {
  URI,
  map: _map,
  extend: _extend,
  extract
};
var Do = /* @__PURE__ */ of(emptyRecord);
var bindTo2 = /* @__PURE__ */ bindTo(Functor);
var let_2 = /* @__PURE__ */ let_(Functor);
var bind2 = /* @__PURE__ */ bind(Chain);
var apS2 = /* @__PURE__ */ apS(Apply);
function elem(E) {
  const go = (a, fa) => E.equals(a, fa.value) || fa.forest.some((tree2) => go(a, tree2));
  return go;
}
var exists = (predicate) => (ma) => predicate(ma.value) || ma.forest.some(exists(predicate));
var chain = flatMap;
var tree = {
  URI,
  map: _map,
  of,
  ap: _ap,
  chain: flatMap,
  reduce: _reduce,
  foldMap: _foldMap,
  reduceRight: _reduceRight,
  traverse: _traverse,
  sequence,
  extract,
  extend: _extend
};

export {
  make,
  getShow,
  getEq2 as getEq,
  drawForest,
  drawTree,
  unfoldTree,
  unfoldForest,
  unfoldTreeM,
  unfoldForestM,
  fold,
  ap,
  flatMap,
  extend,
  duplicate,
  flatten,
  map,
  reduce,
  foldMap,
  reduceRight,
  extract,
  traverse2 as traverse,
  sequence,
  of,
  URI,
  Functor,
  flap2 as flap,
  Pointed,
  Apply,
  apFirst2 as apFirst,
  apSecond2 as apSecond,
  Applicative,
  Chain,
  Monad,
  chainFirst2 as chainFirst,
  Foldable,
  Traversable,
  Comonad,
  Do,
  bindTo2 as bindTo,
  let_2 as let_,
  bind2 as bind,
  apS2 as apS,
  elem,
  exists,
  chain,
  tree,
  Tree_exports
};
