effect
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEffect Basics
Effect基础
The Effect Type
Effect类型
ts
Effect<Success, Error, Requirements>- Lazy: describes a workflow, doesn't execute until run
- Immutable: every operation returns a new Effect
- Aliases: (success),
A(error),E(requirements)R
ts
Effect<Success, Error, Requirements>- 惰性执行:描述一个工作流,直到调用时才会执行
- 不可变:每个操作都会返回一个新的Effect
- 别名:(成功值)、
A(错误值)、E(依赖项)R
Creating Effects
创建Effect
| Combinator | Input | Output |
|---|---|---|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
ts
import { Effect } from "effect"
const ok = Effect.succeed(42)
const err = Effect.fail(new Error("oops"))
const sync = Effect.sync(() => console.log("hi"))
const trySync = Effect.try(() => JSON.parse(str))
const tryAsync = Effect.tryPromise(() => fetch(url))Use for:
suspend- Lazy evaluation with side effects
- Recursive effects (prevents stack overflow)
- Unifying return types
| 组合器 | 输入 | 输出 |
|---|---|---|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
ts
import { Effect } from "effect"
const ok = Effect.succeed(42)
const err = Effect.fail(new Error("oops"))
const sync = Effect.sync(() => console.log("hi"))
const trySync = Effect.try(() => JSON.parse(str))
const tryAsync = Effect.tryPromise(() => fetch(url))suspend- 带有副作用的惰性求值
- 递归Effect(防止栈溢出)
- 统一返回类型
Running Effects
运行Effect
| Runner | Output |
|---|---|
| |
| |
| |
ts
Effect.runSync(program) // sync only
Effect.runPromise(program) // async
Effect.runFork(program) // background fiber| 运行器 | 输出 |
|---|---|
| |
| |
| |
ts
Effect.runSync(program) // 仅同步场景可用
Effect.runPromise(program) // 异步场景
Effect.runFork(program) // 后台纤程When to Run Effects
何时运行Effect
Run effects ONLY at program edges:
- Entry point ()
main - Controller/route handlers
- Event handlers
Anti-pattern - wrapping effects in async functions:
ts
// BAD: runs effect mid-chain
async function getUser(id: string) {
return Effect.runPromise(fetchUser(id))
}
// GOOD: return the effect, run at edge
const getUser = (id: string): Effect.Effect<User, Error> =>
fetchUser(id)仅在程序边界处运行Effect:
- 入口点()
main - 控制器/路由处理器
- 事件处理器
反模式 - 在异步函数中包装Effect:
ts
// 错误示例:在链式调用中途运行Effect
async function getUser(id: string) {
return Effect.runPromise(fetchUser(id))
}
// 正确示例:返回Effect,在边界处运行
const getUser = (id: string): Effect.Effect<User, Error> =>
fetchUser(id)Pipelines
管道操作
| Operator | Purpose |
|---|---|
| Transform success value: |
| Chain effects: |
| Flexible chain (value, fn, Effect, Promise) |
| Side effect, keeps original value |
| Combine effects into tuple/struct |
ts
import { Effect, pipe } from "effect"
const program = pipe(
fetchAmount,
Effect.map((n) => n * 2),
Effect.flatMap((n) => applyDiscount(n)),
Effect.tap((n) => Console.log(`Result: ${n}`))
)
// or with .pipe method
const program2 = fetchAmount.pipe(
Effect.andThen((n) => n * 2),
Effect.andThen((n) => applyDiscount(n))
)
// combine multiple effects
const both = Effect.all([effectA, effectB])
const struct = Effect.all({ a: effectA, b: effectB })| 操作符 | 用途 |
|---|---|
| 转换成功值: |
| 链式调用Effect: |
| 灵活链式调用(支持值、函数、Effect、Promise) |
| 执行副作用,保留原始值 |
| 将多个Effect组合为元组/结构体 |
ts
import { Effect, pipe } from "effect"
const program = pipe(
fetchAmount,
Effect.map((n) => n * 2),
Effect.flatMap((n) => applyDiscount(n)),
Effect.tap((n) => Console.log(`Result: ${n}`))
)
// 或者使用.pipe方法
const program2 = fetchAmount.pipe(
Effect.andThen((n) => n * 2),
Effect.andThen((n) => applyDiscount(n))
)
// 组合多个Effect
const both = Effect.all([effectA, effectB])
const struct = Effect.all({ a: effectA, b: effectB })Generators
生成器
ts
const program = Effect.gen(function* () {
const a = yield* effectA
const b = yield* effectB
return a + b
})Supports standard control flow:
ts
Effect.gen(function* () {
const user = yield* getUser(id)
if (!user) {
return yield* Effect.fail("not found")
}
return user.name
})ts
const program = Effect.gen(function* () {
const a = yield* effectA
const b = yield* effectB
return a + b
})支持标准控制流:
ts
Effect.gen(function* () {
const user = yield* getUser(id)
if (!user) {
return yield* Effect.fail("not found")
}
return user.name
})Gen vs Pipe: When to Use
Gen与Pipe:如何选择
Use when:
Effect.gen- Control flow needed (/
if,else,for, early returns)while - Multiple dependent sequential steps
Use when:
pipe- Linear transformations
- Simple chains without branching
使用的场景:
Effect.gen- 需要控制流(/
if、else、for、提前返回)while - 多个依赖的连续步骤
使用的场景:
pipe- 线性转换
- 无分支的简单链式调用
Tagged Errors
标记式错误
ts
import { Effect, Data } from "effect"
class NotFound extends Data.TaggedError("NotFound")<{
id: string
}> {}
class Unauthorized extends Data.TaggedError("Unauthorized")<{}> {}
const program: Effect.Effect<User, NotFound | Unauthorized> =
Effect.gen(function* () {
// ...
yield* Effect.fail(new NotFound({ id }))
})
// Handle specific errors
program.pipe(
Effect.catchTag("NotFound", (e) => Effect.succeed(null)),
Effect.catchTag("Unauthorized", () => Effect.fail("denied"))
)ts
import { Effect, Data } from "effect"
class NotFound extends Data.TaggedError("NotFound")<{
id: string
}> {}
class Unauthorized extends Data.TaggedError("Unauthorized")<{}> {}
const program: Effect.Effect<User, NotFound | Unauthorized> =
Effect.gen(function* () {
// ...
yield* Effect.fail(new NotFound({ id }))
})
// 处理特定错误
program.pipe(
Effect.catchTag("NotFound", (e) => Effect.succeed(null)),
Effect.catchTag("Unauthorized", () => Effect.fail("denied"))
)Short-Circuiting
短路特性
Effects stop at first error:
ts
Effect.gen(function* () {
yield* task1 // runs
yield* Effect.fail(e) // fails here
yield* task2 // never runs
})Use with to collect all results regardless of failures.
Effect.all{ mode: "either" }Effect会在第一个错误处停止执行:
ts
Effect.gen(function* () {
yield* task1 // 会执行
yield* Effect.fail(e) // 在此处失败
yield* task2 // 永远不会执行
})使用并配置可以收集所有结果,无论是否有失败。
Effect.all{ mode: "either" }Additional Resources
更多资源
For pattern matching
For working with streams
Advanced concurrency (when basics aren't enough)
One-time signaling between fibers
Producer-consumer with back-pressure
Broadcasting messages to multiple subscribers
Limiting concurrent access to a resource
Blocking fibers until a condition/event
Concurrent-safe LRU caching with TTL
模式匹配相关
流处理相关
高级并发(基础功能无法满足时)
纤程间一次性信号传递
带背压的生产者-消费者模式
向多个订阅者广播消息
限制资源的并发访问
阻塞纤程直到条件/事件触发
支持TTL的并发安全LRU缓存