Skip to content

Commit 0a37dfc

Browse files
committed
chore: release v0.3.1 - fix Effect.filterOrFail documentation
- Fix 'Conditionally Branching Workflows' pattern to use Effect.filterOrFail - Update examples from manual if statements to declarative filterOrFail - Simplify predicates from Effect.Effect<boolean> to boolean - Update all text references from Effect.filter to Effect.filterOrFail - Fix API signature in guidelines to show Effect.filterOrFail(predicate, onFailure) - Update 8 files across rules and content directories
1 parent 12e9122 commit 0a37dfc

11 files changed

Lines changed: 615 additions & 655 deletions

content/archived/conditionally-branching-workflows.mdx

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ author: "effect_website"
2626
## Guideline
2727

2828
To make decisions based on a successful value within an `Effect` pipeline, use predicate-based operators:
29-
- **To Validate and Fail:** Use `Effect.filter(predicate)` to stop the workflow if a condition is not met.
29+
- **To Validate and Fail:** Use `Effect.filterOrFail(predicate, onFailure)` to stop the workflow if a condition is not met.
3030
- **To Choose a Path:** Use `Effect.if(condition, { onTrue, onFalse })` or `Effect.gen` to execute different effects based on a condition.
3131

3232
---
@@ -44,7 +44,7 @@ Using these operators turns conditional logic into a composable part of your `Ef
4444

4545
## Good Example: Validating a User
4646

47-
Here, we use `Effect.filter` with named predicates to validate a user before proceeding. The intent is crystal clear, and the business rules (`isActive`, `isAdmin`) are reusable.
47+
Here, we use `Effect.filterOrFail` with named predicates to validate a user before proceeding. The intent is crystal clear, and the business rules (`isActive`, `isAdmin`) are reusable.
4848

4949
```typescript
5050
import { Effect } from "effect";
@@ -61,32 +61,27 @@ const findUser = (id: number): Effect.Effect<User, "DbError"> =>
6161
Effect.succeed({ id, status: "active", roles: ["admin"] });
6262

6363
// Reusable, testable predicates that document business rules.
64-
const isActive = (user: User): Effect.Effect<boolean> =>
65-
Effect.succeed(user.status === "active");
64+
const isActive = (user: User): boolean =>
65+
user.status === "active";
6666

67-
const isAdmin = (user: User): Effect.Effect<boolean> =>
68-
Effect.succeed(user.roles.includes("admin"));
67+
const isAdmin = (user: User): boolean =>
68+
user.roles.includes("admin");
6969

7070
const program = (id: number): Effect.Effect<string, UserError> =>
71-
Effect.gen(function* () {
72-
// Find the user
73-
const user = yield* findUser(id);
74-
75-
// Check if user is active
76-
const active = yield* isActive(user);
77-
if (!active) {
78-
return yield* Effect.fail("UserIsInactive" as const);
79-
}
80-
81-
// Check if user is admin
82-
const admin = yield* isAdmin(user);
83-
if (!admin) {
84-
return yield* Effect.fail("UserIsNotAdmin" as const);
85-
}
86-
71+
findUser(id).pipe(
72+
// Validate user is active using Effect.filterOrFail
73+
Effect.filterOrFail(
74+
isActive,
75+
() => "UserIsInactive" as const
76+
),
77+
// Validate user is admin using Effect.filterOrFail
78+
Effect.filterOrFail(
79+
isAdmin,
80+
() => "UserIsNotAdmin" as const
81+
),
8782
// Success case
88-
return `Welcome, admin user #${user.id}!`;
89-
});
83+
Effect.map((user) => `Welcome, admin user #${user.id}!`)
84+
);
9085

9186
// We can then handle the specific failures in a type-safe way.
9287
const handled = program(123).pipe(
@@ -137,12 +132,12 @@ const program = (id: number) =>
137132
Effect.map((u) => `Welcome, ${u.name}!`),
138133
);
139134

140-
// `Effect.filter` avoids this problem entirely by forcing a failure,
135+
// `Effect.filterOrFail` avoids this problem entirely by forcing a failure,
141136
// which keeps the success channel clean and correctly typed.
142137
```
143138

144139
### Why This is Better
145140

146141
* **It's a Real Bug:** This isn't just a style issue; it's a legitimate logical error that leads to incorrect types and broken code.
147142
* **It's a Common Mistake:** Developers new to functional pipelines often forget that every path must return a value.
148-
* **It Reinforces the "Why":** It perfectly demonstrates *why* `Effect.filter` is superior: `filter` guarantees that if the condition fails, the computation fails, preserving the integrity of the success channel.
143+
* **It Reinforces the "Why":** It perfectly demonstrates *why* `Effect.filterOrFail` is superior: `filterOrFail` guarantees that if the condition fails, the computation fails, preserving the integrity of the success channel.

content/published/conditionally-branching-workflows.mdx

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ author: "effect_website"
2626
## Guideline
2727

2828
To make decisions based on a successful value within an `Effect` pipeline, use predicate-based operators:
29-
- **To Validate and Fail:** Use `Effect.filter(predicate)` to stop the workflow if a condition is not met.
29+
- **To Validate and Fail:** Use `Effect.filterOrFail(predicate, onFailure)` to stop the workflow if a condition is not met.
3030
- **To Choose a Path:** Use `Effect.if(condition, { onTrue, onFalse })` or `Effect.gen` to execute different effects based on a condition.
3131

3232
---
@@ -44,7 +44,7 @@ Using these operators turns conditional logic into a composable part of your `Ef
4444

4545
## Good Example: Validating a User
4646

47-
Here, we use `Effect.filter` with named predicates to validate a user before proceeding. The intent is crystal clear, and the business rules (`isActive`, `isAdmin`) are reusable.
47+
Here, we use `Effect.filterOrFail` with named predicates to validate a user before proceeding. The intent is crystal clear, and the business rules (`isActive`, `isAdmin`) are reusable.
4848

4949
```typescript
5050
import { Effect } from "effect";
@@ -61,32 +61,27 @@ const findUser = (id: number): Effect.Effect<User, "DbError"> =>
6161
Effect.succeed({ id, status: "active", roles: ["admin"] });
6262

6363
// Reusable, testable predicates that document business rules.
64-
const isActive = (user: User): Effect.Effect<boolean> =>
65-
Effect.succeed(user.status === "active");
64+
const isActive = (user: User): boolean =>
65+
user.status === "active";
6666

67-
const isAdmin = (user: User): Effect.Effect<boolean> =>
68-
Effect.succeed(user.roles.includes("admin"));
67+
const isAdmin = (user: User): boolean =>
68+
user.roles.includes("admin");
6969

7070
const program = (id: number): Effect.Effect<string, UserError> =>
71-
Effect.gen(function* () {
72-
// Find the user
73-
const user = yield* findUser(id);
74-
75-
// Check if user is active
76-
const active = yield* isActive(user);
77-
if (!active) {
78-
return yield* Effect.fail("UserIsInactive" as const);
79-
}
80-
81-
// Check if user is admin
82-
const admin = yield* isAdmin(user);
83-
if (!admin) {
84-
return yield* Effect.fail("UserIsNotAdmin" as const);
85-
}
86-
71+
findUser(id).pipe(
72+
// Validate user is active using Effect.filterOrFail
73+
Effect.filterOrFail(
74+
isActive,
75+
() => "UserIsInactive" as const
76+
),
77+
// Validate user is admin using Effect.filterOrFail
78+
Effect.filterOrFail(
79+
isAdmin,
80+
() => "UserIsNotAdmin" as const
81+
),
8782
// Success case
88-
return `Welcome, admin user #${user.id}!`;
89-
});
83+
Effect.map((user) => `Welcome, admin user #${user.id}!`)
84+
);
9085

9186
// We can then handle the specific failures in a type-safe way.
9287
const handled = program(123).pipe(
@@ -143,12 +138,12 @@ const program = (id: number) =>
143138
Effect.map((u) => `Welcome, ${u.name}!`),
144139
);
145140

146-
// `Effect.filter` avoids this problem entirely by forcing a failure,
141+
// `Effect.filterOrFail` avoids this problem entirely by forcing a failure,
147142
// which keeps the success channel clean and correctly typed.
148143
```
149144

150145
### Why This is Better
151146

152147
* **It's a Real Bug:** This isn't just a style issue; it's a legitimate logical error that leads to incorrect types and broken code.
153148
* **It's a Common Mistake:** Developers new to functional pipelines often forget that every path must return a value.
154-
* **It Reinforces the "Why":** It perfectly demonstrates *why* `Effect.filter` is superior: `filter` guarantees that if the condition fails, the computation fails, preserving the integrity of the success channel.
149+
* **It Reinforces the "Why":** It perfectly demonstrates *why* `Effect.filterOrFail` is superior: `filterOrFail` guarantees that if the condition fails, the computation fails, preserving the integrity of the success channel.

0 commit comments

Comments
 (0)