MTL风格电路模拟器:在纯函数与副作用之间找到中间地带
原创MTL风格电路模拟器:在纯函数与副作用之间找到中间地带
从副作用到纯度:电路模拟器的两次转向
我写电路模拟器时总在同一个地方卡住。信号传播天然带着副作用,延时让结果依赖时间顺序。把副作用全塞进 IO,代码写起来顺手,但测试和推理就麻烦了。我见过有人把整个模拟器写成纯函数,信号传播变成值变换,看起来很漂亮,可一旦要支持探针输出、时间查询,纯函数的路就走不通了。写模拟器的人都会遇到这种纠结。
作者在这篇文章里复盘了自己的两次尝试 来源:原文。第一版是个“非常副作用”的实现,get_signal 的签名是 Wire -> IO Signal 来源:原文。这个签名给了实现完全的自由,它可以在 IO 上下文里做各种顽皮的事,读文件或者发射导弹,编译器都不会拦着 来源:原文。副作用全裸露在类型上,调用方一看就知道这里能做坏事。
第二版试图做纯函数。作者称之为“雄心勃勃的尝试”来源:原文,但没有展开讲它怎么失败的,只留下这个说法。纯函数版本听起来更优雅,但对电路模拟器来说,时间推进、延时调度和探针输出都离不开状态和时序,纯函数的路很窄。
在两次尝试之后,作者想起了中间地带。这个模式叫 mtl-style effects,是 final tagless 编码的一种特定类型 来源:原文,在生产级 Haskell 代码里很常见 来源:原文。他说的“中间地带”,意思是在 IO 的完全自由与纯函数的完全约束之间,找到一层接口,把模拟器需要的操作列出来,让实现只知道这层接口。类型类把操作列出来,调用方只能看到这些操作,看不到背后的 IO。
mtl-style核心:类型类约束如何隐藏副作用
做法很直接,把模拟器需要支持的操作抽象成一个类型类。作者给出的 CircuitOperations 有八个方法,make_wire、get_signal、set_signal、add_action、after_delay、get_time、probe_output、propagate 来源:原文。这八个操作覆盖了模拟器的全部需求,组件定义也在这套接口之上完成,比如 inverter 的类型从 Wire -> Wire -> IO 变成基于接口的版本 来源:原文。
新旧签名最关键的差别在 get_signal。旧版是 Wire -> IO Signal,实现知道自己在 IO 上下文里,可以做任何 IO 允许的事 来源:原文。新版是 CircuitOperations m => Wire -> m Signal,上下文被藏起来了 来源:原文。实现不知道 m 到底是什么,只知道它支持 CircuitOperations。编译器会在稍后选择具体的 m,把它塞进变量里,但实现看不到 来源:原文。旧版的自由来自签名,新版的约束也来自签名。
这个设计的直接效果很明确。即使函数最终运行在 IO 上下文,实现也不知道这一点,所以它无法发射导弹 来源:原文。它唯一能做的,就是调用 CircuitOperations 接口里规定的操作 来源:原文。这等于把“能做什么”画了一道线,线的另一边是不可见的。
画这道线需要经验。作者说“绘制这个边界需要经验和品味”来源:原文,我认同这个说法。操作集合选多了,接口会失去意义;选少了,模拟器表达不了它需要的东西。这个判断依赖对问题域的理解,不是一个公式能给出的。
多源交叉验证:HN社区反应与原文设计判断
Hacker News 上这篇帖子目前只有 1 个点,0 条评论 来源:HN。对于一个涉及 Haskell 类型类设计、final tagless 编码的技术文来说,这个反应确实冷清。我不确定为什么,可能受众太小,也可能时机不合适。
原文本身内容完整,代码示例、类型签名、设计权衡都写得很清楚,从 IO 到类型类的演进过程也讲明白了 来源:原文。技术细节和社区反应之间存在反差,但我不确定这个反差说明什么。也许这个主题太新,也许讨论 Haskell 的人本来就少。但 HN 冷清不代表文章没价值,技术博客的传播本来就慢。
作者自己的判断是,mtl-style 是生产 Haskell 代码里的常见模式 来源:原文。纯函数方案被他称为“雄心勃勃的尝试”来源:原文,这个形容词带着一点保留。雄心勃勃不意味着好用,这篇文章展示的正是中间路线 来源:原文。
这背后是边界位置的问题。纯函数和 IO 各有一个极端,mtl-style 站在中间,它不消灭副作用,只是把副作用的范围限制在一组操作里 来源:原文。对电路模拟器这种需要时序传播的系统,这个中间地带让代码在保持功能的同时,还能保留纯函数式的推理方式 来源:原文。
原文:
MTL-Style Circuit Simulator · 来源:Hacker News
作者:itfan123 值班编辑 · 发布于 2026年10月28日
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123




