Building Pipelines
Learn how to compose complex logic into readable, safe pipelines using Result and Option.
Pipelines are the heart of functional programming. Instead of nesting if statements or using try-catch for control flow, you chain operations together. This creates a "railway" where data flows through the happy path, but automatically switches to the error track the moment something goes wrong.
The Railway Mental Model
In a pipeline, every step either:
- Stays on the track: Returns
Ok(value)orSome(value), passing it to the next function. - Derails: Returns
Err(error)orNone, bypassing all subsequent steps until it hits a handler.
This approach ensures that your core business logic isn't buried under error checks.
Composing a Business Flow
A synchronous pipeline for in-memory validation and transformation:
import { } from "@carbonteq/fp";
type = { : string; : number; : string };
type = { : string; : number };
const = 29.99;
const = 100;
const = (: ): <, string> =>
!. ? .("Product ID required")
: . <= 0 ? .("Quantity must be positive")
: !. ? .("User ID required")
: .();
const = (: ): <, string> =>
. > ? .("Insufficient stock") : .();
export function (: ): <, string | string[]> {
return .()
.([, ])
.(() => ({
: `ORD-${.()}`,
: . * ,
}))
.(() => .(`Processed: ${.}`));
}An asynchronous pipeline with database/API calls. Use .toPromise() at the end:
import { } from "@carbonteq/fp";
type = { : string; : string };
type = { : string; : string };
declare function (: string): <boolean>;
declare function (: string): <string>;
declare function (: string, : string): <>;
async function (: ): <<, string>> {
const = await (.);
return ? .("Email taken") : .();
}
async function (: ): <<, string>> {
return .(
async () => {
const = await (.);
return (., );
},
() => "Failed to create user",
).();
}
export async function (: ): <<, string | string[]>> {
return .()
.([
() => (..("@") ? .() : .("Invalid email")),
() => (.. >= 8 ? .() : .("Password too short")),
])
.()
.()
.(() => .(`Registered: ${.}`))
.();
}Validation with Error Accumulation
The .validate() operator runs multiple validators and collects all errors:
import { } from "@carbonteq/fp";
const = (: string) =>
. >= 8 ? .() : .("Min 8 characters");
const = (: string) =>
/\d/.() ? .() : .("Must contain a number");
const = (: string) =>
/[!@#$%^&*]/.() ? .() : .("Needs special character");
// Collects ALL failing rules, not just the first
const = (: string) =>
.().([, , ]);
const = ("abc");
// Err(["Min 8 characters", "Must contain a number", "Needs special character"])
const = ("MyP@ssw0rd!");
// Ok("MyP@ssw0rd!")Error Transformation
Keep errors structured internally, format them at the edge.
Transform with mapErr
import { } from "@carbonteq/fp";
type = { : string; : string };
const = (: string): => ({
: "VALIDATION_ERROR",
: ,
});
const = .("email is required").();
// Err({ code: "VALIDATION_ERROR", message: "email is required" })Enrich with mapBoth
import { } from "@carbonteq/fp";
type <> = & { : number };
const = .({ : "u1" }).(
() => ({ ..., : .() }),
() => ({ : (), : .() }),
);Debugging with tap and tapErr
Add logging without breaking the pipeline:
import { } from "@carbonteq/fp";
type = { : string; : string[] };
declare function (: ): <, string>;
declare function (: ): <, string>;
const = (: ) =>
.()
.(() => .(`[START] Processing ${.}`))
.()
.(() => .(`[VALID] ${.}`))
.()
.(() => .(`[CHARGED] ${.}`))
.(() => .(`[FAILED] ${}`));Fallback Chains with orElse
Recover from errors with fallback strategies:
import { } from "@carbonteq/fp";
type = { : string };
declare function (): <, Error>;
declare function (): <, Error>;
const : = { : "https://api.example.com" };
const = () =>
()
.()
.(() => .());Combining Multiple Results
Use Result.all when all must succeed, or Result.any for first-success:
import { } from "@carbonteq/fp";
declare function (: string): <{ : string }, string>;
declare function (: string): <{ : number }, string>;
// All must succeed
const = (: string, : string) =>
.((), ())
.(([, ]) => ({ : ., : . }));
// First success wins
declare function (): <string, Error>;
declare function (): <string, Error>;
const = () => .((), ());Next Steps
- Check the API Cheatsheet for a quick reference of all operators.
- Learn about Async Handling for Promise-based pipelines.