Sequential Building with seq()
Compose computations step by step with automatic context threading
Understanding Sequential Building
seq() is typelang's monadic builder for sequential programs. Think of it as a pipeline where each step can access all previous results.
Each .let() step binds a new variable into the context. .do() runs a side effect without binding. .return() produces the final value.
The context is automatically typed—TypeScript infers what's available at each step.
No mutation needed: each step produces a new frozen context object.
Code Example
// Build a user profile sequentially
const buildProfile = (userId: string) =>
seq()
.let(() => fetchUser(userId)) // ctx.v1
.let((user) => fetchPosts(user.id)) // ctx.v2
.let((posts, ctx) => fetchFollowers((ctx!["v1"] as User).id)) // ctx.v3
.do((followers, ctx) => Console.op.log(`Building profile for ${(ctx!["v1"] as User).name}`))
.return((followers, ctx) => ({
user: ctx!["v1"] as User,
postCount: (ctx!["v2"] as Post[]).length,
followerCount: followers.length,
}));
// Auto-named context keys track all values:
// After first .let(): ctx.v1 = User
// After second .let(): ctx.v2 = Post[]
// After third .let(): ctx.v3 = User[]
Key Points
- .let(fn) binds the result to auto-named context key (v1, v2, ...)
- .do(fn) runs an effect without storing a new binding
- .when(pred, fn) conditionally runs an effect
- .return(fn) produces the final value using last and ctx
- Context grows with each .let(), accessible via ctx['v1'], ctx['v2'], etc.