# how can i avoid the pyramid of doom by using chains in fp-ts?

There is a solution to the problem, and it’s called “do notation”. It’s been available in `fp-ts-contrib` for a while, but it now also has a version baked into `fp-ts` itself using the `bind` function (which is defined on all monadic types). The basic idea is similar to what I was doing below – we bind computation results to a particular name, and track those names inside a “context” object as we go along. Here’s the code:

``````pipe(
TE.of<Error, string>('one'),
TE.bindTo('one'), // start with a simple struct {one: 'one'}
TE.bind('two', op1), // the payload now contains `one`
TE.bind('three', op2), // the payload now contains `one` and `two`
TE.bind('four', op3), // the payload now contains `one` and `two` and `three`
TE.map(x => x.four)  // we can discharge the payload at any time
)
``````

## Original Answer below

I’ve come up with a solution that I’m not very proud of, but I’m sharing it for possible feedback!

Firstly, define some helper functions:

``````function mapS<I, O>(f: (i: I) => O) {
return <R extends { [k: string]: I }>(vals: R) =>
Object.fromEntries(Object.entries(vals).map(([k, v]) => [k, f(v)])) as {
[k in keyof R]: O;
};
}
const TEofStruct = <R extends { [k: string]: any }>(x: R) =>
mapS(TE.of)(x) as { [K in keyof R]: TE.TaskEither<unknown, R[K]> };
``````

`mapS` allows me to apply a function to all values in an object (subquestion 1: is there a builtin function that would allow me to do this?). `TEofStruct` uses this function to turn a struct of values into a struct of `TaskEither`s for those values.

My basic idea is to accumulate the new value along with the previous values using `TEofStruct` and `sequenceS`. So far it looks like this:

``````pipe(
TE.of({
one: 'one',
}),
TE.chain((x) =>
sequenceTE({
two: op1(x),
...TEofStruct(x),
})
),
TE.chain((x) =>
sequenceTE({
three: op2(x),
...TEofStruct(x),
})
),
TE.chain((x) =>
sequenceTE({
four: op3(x),
...TEofStruct(x),
})
)
);
``````

It feels like I could write some kind of helper function that combines `sequenceTE` with `TEofStruct` to reduce the boilerplate here, but I’m still not sure overall if this is the right approach, or if there is a more idiomatic pattern!

CLICK HERE to find out more related problems solutions.

Scroll to Top