非确定性与状态管理:Eff中State、List、Choose与Memo效果实战清单

发布时间:2026/8/22 14:31:23
非确定性与状态管理:Eff中State、List、Choose与Memo效果实战清单 非确定性与状态管理Eff中State、List、Choose与Memo效果实战清单【免费下载链接】effEff monad for cats - https://atnos-org.github.io/eff项目地址: https://gitcode.com/gh_mirrors/eff/effEff是面向 Scala 的可扩展效果Extensible Effects函子库常被称作 cats 生态中的 Eff monad。它用效果栈替代冗长的 monad transformer 组合让状态管理State、非确定性Choose、多值收集List与记忆化缓存Memo四种效果像搭积木一样自由叠加。本文用一份实战清单帮你在 10 分钟内搞懂这四个效果各自解决什么问题、何时该用、以及如何组合成可运行的效果栈。 Eff monad 是什么为什么需要效果栈传统方案中同时需要 Reader、Writer、State 时要层层包裹 monad transformer类型签名爆炸。Eff 的核心思想是把所有效果打包进一个扁平的 R 类型集合效果栈每个效果只负责发出请求 解释请求两件事。核心数据结构定义在core/src/main/scala/org/atnos/eff/Eff.scala它本质上是Free-er monad一个纯值分支 一个效果联合体 续延continuation分支。效果栈由Unions效果类型集合和Union单个效果的解释器实现分别见core/src/main/scala/org/atnos/eff/Unions.scala与core/src/main/scala/org/atnos/eff/Union.scala。 心智模型Eff 程序里要做什么副作用的纯描述运行interpret时才决定怎么做。 四个效果速览一份对照清单效果模块位置解决什么问题典型场景Statestate/沿计算传递可变状态计数器、请求上下文Listlist/一次计算返回多个结果枚举所有可能路径Choosechoose/表达二选一的非确定性搜索、随机选择Memofuture/memo 子模块按 key 缓存昂贵计算递归去重、配置缓存 State 效果把可变状态关进纯函数State 效果让程序在保持纯函数的前提下读写一个贯穿始终的状态值内部由 cats 的State支撑。源码入口效果定义state/src/main/scala/org/atnos/eff/StateEffect.scala常用操作state/src/main/scala/org/atnos/eff/StateCreation.scala它提供四个最经典的操作覆盖 90% 的状态需求get—— 读取当前状态put—— 写入新状态gets—— 读取并用函数映射状态modify—— 用函数原地修改状态运行 State 效果只需调用runState并提供初始值最终拿到结果值 最终状态。适合订单累计金额、解析器位置跟踪、工作流进度等。 List 效果让一次计算产出 N 个结果List 效果list/src/main/scala/org/atnos/eff/ListEffect.scala把计算结果从单个值扩展为可能返回多个值。每个中间步骤的结果会被自动组合笛卡尔积最终runList得到一个结果列表。适用场景配置枚举把所有合法参数组合列出来查询扇出一次查询命中多条记录后续步骤对每条都执行与 Choose 联动非确定性选择的所有分支结果统一收集 Choose 效果非确定性编程的正确打开方式Choose 效果建模非确定性选择源码见choose/src/main/scala/org/atnos/eff/ChooseEffect.scalazero—— 表示没有结果该分支失败plus(a1, a2)—— 在两个分支中任选其一chooseFrom(list)—— 从一组候选值中任选关键在于它只描述选择不执行选择。运行期用任意具有 Alternative 实例的 F 来解释解释为List→ 收集所有可能结果plus变成两个都要解释为Option→ 返回第一个成功结果短路求值同一份程序换解释器就能在穷举所有方案和找任一可行解之间切换这是 Eff 非确定性最优雅的地方。随机数辅助工具见choose/src/main/scala/org/atnos/eff/Rand.scala。⚡ Memo 效果给昂贵计算加上记忆化缓存Memo 效果future/src/main/scala/org/atnos/eff/MemoEffect.scala按 key缓存计算结果重复调用同一 key 直接命中缓存避免重复计算。核心操作在future/src/main/scala/org/atnos/eff/MemoCreation.scalamemoize(key, computation)即带缓存地执行缓存抽象为Cache见core/src/main/scala/org/atnos/eff/Cache.scala内置两种默认实现core/src/main/scala/org/atnos/eff/ConcurrentHashMapCache.scala无界并发哈希缓存—— 简单直接弱引用缓存—— 条目可被 GC 回收适合长生命周期场景典型收益指数级递归如斐波那契降为线性昂贵的外部数据查询只执行一次。你也可以接 ScalaCache 等第三方库实现自定义 Cache。 组合实战四效果如何在一个栈里协作Eff 的精髓是组合。一个真实程序里四种效果常同时出现State[Int] ← 维护计数器 Choose ← 搜索分支 List ← 收集所有可行解 Memoized ← 缓存重复子问题工作流固定三步写程序在Eff[效果栈, A]中自由调用 get/put、zero/plus、memoize 等操作此时程序是纯数据定解释为栈中每个效果挂一个解释器Interpret实例见core/src/main/scala/org/atnos/eff/Interpret.scala跑运行调用runMemo(runState(runChoose(...)(初始状态)))(缓存)逐层求值拿到最终结果。效果栈的转换、裁剪如把某效果编译掉在core/src/main/scala/org/atnos/eff/Translate.scala中实现官方文档的 working with different effect stacks 章节有完整示例。✅ 新人上手清单先用State替代var体会纯函数里管状态模块state/用List枚举组合结果理解多值语义模块list/用Choose写一次穷举 vs 取首解双解释器程序模块choose/给递归算法加Memo观察重复 key 命中缓存模块future/阅读测试用例效果的标准用法都在all/src/test/scala/org/atnos/eff/下StateEffectSpec.scala、ListEffectSpec.scala、ChooseEffectSpec.scala查阅版本演进记录了解 API 变化notes/目录下的各版本说明如notes/8.0.0.markdown 小结State 管记住List 管多值Choose 管选择Memo 管别算两遍。掌握这四个效果你就拥有了 Eff 效果栈中最实用的四块积木。【免费下载链接】effEff monad for cats - https://atnos-org.github.io/eff项目地址: https://gitcode.com/gh_mirrors/eff/eff创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考