State Management by andrueandersoncs/claude-skill-effect-ts
npx skills add https://github.com/andrueandersoncs/claude-skill-effect-ts --skill 'State Management'Effect 提供了函数式可变状态原语:
所有类型都是纤程安全的,并能正确处理并发访问。
import { Effect, Ref } from "effect"
const program = Effect.gen(function* () {
const counter = yield* Ref.make(0)
const current = yield* Ref.get(counter)
yield* Ref.set(counter, 10)
yield* Ref.update(counter, (n) => n + 1)
const old = yield* Ref.getAndSet(counter, 0)
const newValue = yield* Ref.updateAndGet(counter, (n) => n + 5)
const [oldVal, result] = yield* Ref.modify(counter, (n) => [
n,
n * 2
])
})
const atomicIncrement = Effect.gen(function* () {
const counter = yield* Ref.make(0)
yield* Effect.all([
Ref.update(counter, (n) => n + 1),
Ref.update(counter, (n) => n + 1),
Ref.update(counter, (n) => n + 1)
], { concurrency: "unbounded" })
return yield* Ref.get(counter)
})
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
const CounterService = Effect.gen(function* () {
const ref = yield* Ref.make(0)
return {
increment: Ref.update(ref, (n) => n + 1),
decrement: Ref.update(ref, (n) => n - 1),
get: Ref.get(ref),
reset: Ref.set(ref, 0)
}
})
const CounterLive = Layer.effect(Counter, CounterService)
用于需要运行副作用的更新:
import { Effect, SynchronizedRef } from "effect"
const program = Effect.gen(function* () {
const ref = yield* SynchronizedRef.make({ count: 0, lastUpdated: Date.now() })
yield* SynchronizedRef.updateEffect(ref, (state) =>
Effect.gen(function* () {
yield* Effect.log("Updating state")
return {
count: state.count + 1,
lastUpdated: Date.now()
}
})
)
const result = yield* SynchronizedRef.modifyEffect(ref, (state) =>
Effect.gen(function* () {
const newCount = state.count + 1
yield* sendMetric("counter", newCount)
return [
newCount,
{ ...state, count: newCount }
]
})
)
})
更新需要 API 调用
更新需要日志记录/指标收集
更新依赖于外部状态
更新需要错误处理
// 带异步刷新的缓存 const cache = yield* SynchronizedRef.make<Data | null>(null)
const refreshCache = SynchronizedRef.updateEffect(cache, () => Effect.tryPromise(() => fetchLatestData()) )
用于需要通知订阅者的状态:
import { Effect, SubscriptionRef, Stream } from "effect"
const program = Effect.gen(function* () {
const ref = yield* SubscriptionRef.make(0)
const changes = yield* SubscriptionRef.changes(ref)
yield* Effect.fork(
Stream.runForEach(changes, (value) =>
Effect.log(`Value changed to: ${value}`)
)
)
yield* SubscriptionRef.set(ref, 1)
yield* SubscriptionRef.update(ref, (n) => n + 1)
yield* SubscriptionRef.set(ref, 10)
})
const configRef = yield* SubscriptionRef.make(initialConfig)
const subscriber1 = Effect.fork(
Stream.runForEach(
SubscriptionRef.changes(configRef),
(config) => updateService1(config)
)
)
const subscriber2 = Effect.fork(
Stream.runForEach(
SubscriptionRef.changes(configRef),
(config) => updateService2(config)
)
)
yield* SubscriptionRef.set(configRef, newConfig)
| 功能 | Ref | SynchronizedRef | SubscriptionRef |
|---|---|---|---|
| 基础获取/设置 | ✅ | ✅ | ✅ |
| 原子更新 | ✅ | ✅ | ✅ |
| 副作用更新 | ❌ | ✅ | ❌ |
| 变更通知 | ❌ | ❌ | ✅ |
| 使用场景 | 简单状态 | 异步更新 | 响应式状态 |
class Counter extends Context.Tag("Counter")<
Counter,
{
readonly increment: Effect.Effect<number>
readonly decrement: Effect.Effect<number>
readonly get: Effect.Effect<number>
}
>() {}
const CounterLive = Layer.effect(
Counter,
Effect.gen(function* () {
const ref = yield* Ref.make(0)
return {
increment: Ref.updateAndGet(ref, (n) => n + 1),
decrement: Ref.updateAndGet(ref, (n) => n - 1),
get: Ref.get(ref)
}
})
)
type State = "idle" | "loading" | "success" | "error"
const stateMachine = Effect.gen(function* () {
const state = yield* Ref.make<State>("idle")
const transition = (from: State, to: State) =>
Ref.modify(state, (current) =>
current === from
? [true, to]
: [false, current]
)
return {
state: Ref.get(state),
startLoading: transition("idle", "loading"),
succeed: transition("loading", "success"),
fail: transition("loading", "error"),
reset: Ref.set(state, "idle")
}
})
const accumulator = Effect.gen(function* () {
const items = yield* Ref.make<Array<Item>>([])
return {
add: (item: Item) => Ref.update(items, (arr) => [...arr, item]),
getAll: Ref.get(items),
clear: Ref.set(items, []),
count: Effect.map(Ref.get(items), (arr) => arr.length)
}
})
如需完整的状态管理文档,请查阅 ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt。
搜索以下章节:
每周安装量
0
代码仓库
GitHub 星标数
5
首次出现时间
1970年1月1日
安全审计
Effect provides functional mutable state primitives:
All are fiber-safe and work correctly with concurrent access.
import { Effect, Ref } from "effect"
const program = Effect.gen(function* () {
const counter = yield* Ref.make(0)
const current = yield* Ref.get(counter)
yield* Ref.set(counter, 10)
yield* Ref.update(counter, (n) => n + 1)
const old = yield* Ref.getAndSet(counter, 0)
const newValue = yield* Ref.updateAndGet(counter, (n) => n + 5)
const [oldVal, result] = yield* Ref.modify(counter, (n) => [
n,
n * 2
])
})
const atomicIncrement = Effect.gen(function* () {
const counter = yield* Ref.make(0)
yield* Effect.all([
Ref.update(counter, (n) => n + 1),
Ref.update(counter, (n) => n + 1),
Ref.update(counter, (n) => n + 1)
], { concurrency: "unbounded" })
return yield* Ref.get(counter)
})
const CounterService = Effect.gen(function* () {
const ref = yield* Ref.make(0)
return {
increment: Ref.update(ref, (n) => n + 1),
decrement: Ref.update(ref, (n) => n - 1),
get: Ref.get(ref),
reset: Ref.set(ref, 0)
}
})
const CounterLive = Layer.effect(Counter, CounterService)
For updates that require running effects:
import { Effect, SynchronizedRef } from "effect"
const program = Effect.gen(function* () {
const ref = yield* SynchronizedRef.make({ count: 0, lastUpdated: Date.now() })
yield* SynchronizedRef.updateEffect(ref, (state) =>
Effect.gen(function* () {
yield* Effect.log("Updating state")
return {
count: state.count + 1,
lastUpdated: Date.now()
}
})
)
const result = yield* SynchronizedRef.modifyEffect(ref, (state) =>
Effect.gen(function* () {
const newCount = state.count + 1
yield* sendMetric("counter", newCount)
return [
newCount,
{ ...state, count: newCount }
]
})
)
})
Updates require API calls
Updates require logging/metrics
Updates depend on external state
Updates need error handling
// Cache with async refresh const cache = yield* SynchronizedRef.make<Data | null>(null)
const refreshCache = SynchronizedRef.updateEffect(cache, () => Effect.tryPromise(() => fetchLatestData()) )
For state that needs to notify subscribers:
import { Effect, SubscriptionRef, Stream } from "effect"
const program = Effect.gen(function* () {
const ref = yield* SubscriptionRef.make(0)
const changes = yield* SubscriptionRef.changes(ref)
yield* Effect.fork(
Stream.runForEach(changes, (value) =>
Effect.log(`Value changed to: ${value}`)
)
)
yield* SubscriptionRef.set(ref, 1)
yield* SubscriptionRef.update(ref, (n) => n + 1)
yield* SubscriptionRef.set(ref, 10)
})
const configRef = yield* SubscriptionRef.make(initialConfig)
const subscriber1 = Effect.fork(
Stream.runForEach(
SubscriptionRef.changes(configRef),
(config) => updateService1(config)
)
)
const subscriber2 = Effect.fork(
Stream.runForEach(
SubscriptionRef.changes(configRef),
(config) => updateService2(config)
)
)
yield* SubscriptionRef.set(configRef, newConfig)
| Feature | Ref | SynchronizedRef | SubscriptionRef |
|---|---|---|---|
| Basic get/set | ✅ | ✅ | ✅ |
| Atomic updates | ✅ | ✅ | ✅ |
| Effectful updates | ❌ | ✅ | ❌ |
| Change notifications | ❌ | ❌ | ✅ |
| Use case | Simple state | Async updates | Reactive state |
class Counter extends Context.Tag("Counter")<
Counter,
{
readonly increment: Effect.Effect<number>
readonly decrement: Effect.Effect<number>
readonly get: Effect.Effect<number>
}
>() {}
const CounterLive = Layer.effect(
Counter,
Effect.gen(function* () {
const ref = yield* Ref.make(0)
return {
increment: Ref.updateAndGet(ref, (n) => n + 1),
decrement: Ref.updateAndGet(ref, (n) => n - 1),
get: Ref.get(ref)
}
})
)
type State = "idle" | "loading" | "success" | "error"
const stateMachine = Effect.gen(function* () {
const state = yield* Ref.make<State>("idle")
const transition = (from: State, to: State) =>
Ref.modify(state, (current) =>
current === from
? [true, to]
: [false, current]
)
return {
state: Ref.get(state),
startLoading: transition("idle", "loading"),
succeed: transition("loading", "success"),
fail: transition("loading", "error"),
reset: Ref.set(state, "idle")
}
})
const accumulator = Effect.gen(function* () {
const items = yield* Ref.make<Array<Item>>([])
return {
add: (item: Item) => Ref.update(items, (arr) => [...arr, item]),
getAll: Ref.get(items),
clear: Ref.set(items, []),
count: Effect.map(Ref.get(items), (arr) => arr.length)
}
})
For comprehensive state management documentation, consult ${CLAUDE_PLUGIN_ROOT}/references/llms-full.txt.
Search for these sections:
Weekly Installs
0
Repository
GitHub Stars
5
First Seen
Jan 1, 1970
Security Audits
Angular开发者指南:从项目创建到组件与信号式状态管理的最佳实践
532 周安装