Mercury 工程师 Ian Duncan 在 Haskell 官方博客新系列 Haskellers from the trenches 中写了一篇文章,题目是《A Couple Million Lines of Haskell: Production Engineering at Mercury》。

里面最抓人的数字,是约 200 万行 Haskell。原文也说清楚了:这是去掉注释等内容后的 Haskell 代码量,不等同于 Mercury 的全部代码规模。

有意思的地方不只是“冷门语言跑进金融系统”。更反常的是,Mercury 是一家金融科技公司,约 1500 名员工,服务 30 万以上企业客户,2025 年交易量达到 2480 亿美元;而多数工程师入职前并不会 Haskell。

所以这篇文章真正要回答的问题不是:Haskell 到底优不优雅。

更硬的问题是:在强监管、快速扩张、很多新人加入的组织里,一门不大众的语言,能不能靠工程边界稳定落地。

Mercury 的反常识:不是选了 Haskell,而是敢把它用大

金融后端通常更偏爱 Java、C#、Go,或者更保守的 JVM 技术栈。理由很现实:招聘池大,生态成熟,工具链稳,合规和监控经验也多。

Mercury 长期使用 Haskell,就天然要付两笔成本。

新人要学。团队知识也更容易集中在少数熟手身上。

Ian Duncan 没有把答案写成“编译器会拯救一切”。他强调的可靠性,是 adaptive capacity:系统吸收变化、降级运行、让操作者理解并调整的能力。

这句话很关键。可靠性不只是“没有 bug”,也不是一次性证明正确。生产系统每天都在变:业务规则变,监管要求变,外部 API 变,团队成员也在变。

Haskell 在 Mercury 里的角色,更像 operational aid。类型系统不是论文里的 correctness proof,而是运营辅助工具:把容易忘、容易错、容易出事故的知识,压进接口和类型里。

用一张表看,会更清楚:

问题常见后端做法Mercury 文中强调的做法我的判断
招聘与上手选 Java、Go、C#,降低招聘摩擦多数工程师入职后再学 Haskell可行,但要用培训和工具链补成本
可靠性来源测试、文档、代码审查、事故复盘类型边界、可理解架构、提前评审不是替代测试,而是减少低级误用
高风险流程靠规范提醒“不要这样写”让危险路径不能被直接调用比口头规则更适合快速扩张团队
适用范围通用企业后端金融交易、事件发布、状态机等高约束场景不能外推到所有公司、所有金融系统

这也是这篇文章克制的地方。它没有说 Haskell 因为“纯粹性”就能自动解决生产问题。

现实系统里有数据库连接池、重试、缓存、并发状态和外部 API。副作用不会消失。问题是,能不能把副作用关在更窄、更清楚的边界里。

类型系统真正管住的,是那些“漏一步就出事”的流程

原文最有价值的例子,是事务和事件发布。

很多事故不是算法太难,而是流程被写散了。比如先写数据库,再发事件。两步必须保持一致,但工程师赶进度时,很容易漏掉某一步,或者在错误位置调用。

传统做法是写文档、加 code review、在团队频道里反复提醒:请用某个安全方法,不要自己先写事务再发事件。

这类提醒当然有用,但它有个弱点:它假设每个人在每次改代码时,都记得旧规则。

Mercury 的做法,是把流程封装成 Transact。开发者可以 record 事务,也可以 emit 事件,但真正执行只有一个出口:commit。

commit 内部负责把数据库提交和事件发布放进安全路径。这样,正确做法不再是一条需要背下来的规矩,而是代码里唯一能走通的门。

这就是“类型系统作为运营记忆”的意思。

它不负责替人理解业务,也不保证所有需求都正确。它做的是另一件事:把已经确认过的危险区,用接口围起来,让后来者少走错路。

这对后端和基础设施工程师有直接影响。

如果你维护的是支付、账务、订单状态机、消息投递、权限变更这类系统,真正该检查的不是“我们有没有文档”。而是这几件事:

  • 高风险操作有没有唯一入口;
  • 调用顺序能不能被类型或接口约束;
  • 危险方法是不是还暴露给普通业务代码;
  • code review 里反复提醒的规则,能不能下沉到库设计里。

换句话说,不一定要换 Haskell。用 Kotlin、Rust、TypeScript,甚至 Go,也能做一部分边界设计。只是表达能力、样板代码和团队习惯不同。

工具有差别,问题是同一个:别把组织记忆只放在人的脑子里。

对管理者的启示:别先问换不换语言,先问边界谁来守

技术管理者读这篇文章,最不该得到的结论是“我们也该上 Haskell”。

Mercury 的案例只能说明:在特定团队、特定业务压力和长期投入下,Haskell 可以支撑大规模生产系统。它不能证明 Haskell 适合所有金融系统,也不能证明冷门语言适合所有大公司。

更现实的问题是:当团队变大,新人变多,哪些规则必须进入代码结构,哪些规则可以留在培训材料里。

如果一个风险点每次都靠资深工程师口头把关,那它就是组织扩张的隐性瓶颈。人少时还能靠熟人网络兜住,人一多,就会“口耳相传,递减失真”。

对管理者,动作可以更具体一点:

角色该做什么不该做什么
后端 / 基础设施负责人盘点事故复盘里反复出现的误用路径,把它们改成库和接口约束只增加文档、流程和审批层级
技术管理者给关键基础库、类型建模、内部培训留出时间把类型设计当成少数专家的个人洁癖
架构评审者关注“非法路径是否仍可调用”只看模块图和服务拆分是否好看

这里也有现实限制。

原文没有给出完整事故率、可用性指标、培训成本,也没有证明这套体系在跨语言、跨服务场景中同样强。Mercury 还在申请美国 OCC national bank charter,并不是已经获得银行牌照。

所以判断要收住:这是一份有价值的生产工程样本,不是通用处方。

接下来真正该看的,不是 Haskell 会不会变成金融行业主流。更该看三件事:

  • 新人培训能否跟上团队继续扩张;
  • 类型边界能否覆盖更多跨服务流程;
  • 监管要求变复杂后,这套工程纪律是否还能保持低摩擦。

回到开头那个数字,约 200 万行 Haskell 真正说明的不是“函数式语言赢了”。

它说明另一件更朴素的事:生产系统靠人记规矩,规模一大就会漏。能把规矩写进边界,经验才不会随人流动而流失。