import * as A from "../Array";
import { identity } from "../Function";
import { map_ } from "./functor";
import type { Tree } from "./model";
/*
* -------------------------------------------
* Monad Tree
* -------------------------------------------
*/
export const chain_ = (ma: Tree, f: (a: A) => Tree): Tree => {
const { value, forest } = f(ma.value);
const combine = A.getMonoid>().combine_;
return {
value,
forest: combine(
forest,
A.map_(ma.forest, (a) => chain_(a, f))
)
};
};
export const chain = (f: (a: A) => Tree) => (ma: Tree): Tree => chain_(ma, f);
export const flatten: (mma: Tree>) => Tree = chain(identity);
export const tap_ = (ma: Tree, f: (a: A) => Tree): Tree => chain_(ma, (a) => map_(f(a), () => a));
export const tap = (f: (a: A) => Tree) => (ma: Tree): Tree => tap_(ma, f);