Enterprise Haskell at H-E-B
Enterprise Haskell at H-E-B
H-E-B 的企业级 Haskell 应用
Joshua Miller | July 16, 2026 Joshua Miller | 2026年7月16日
[Haskellers from the trenches] #Production #H-E-B [来自一线阵地的 Haskellers] #生产环境 #H-E-B
This article is the second installment of our series “Haskellers from the trenches”, where we invite experienced engineers to talk about their subjects of expertise, best practices, and production tales with Haskell. 本文是我们“来自一线阵地的 Haskellers”系列文章的第二篇。在该系列中,我们邀请经验丰富的工程师分享他们的专业领域、最佳实践以及使用 Haskell 进行生产开发的真实故事。
The mainframe problem
大型机难题
When I joined H-E-B back in 2018, I was entering a world far removed from any of my previous roles in technology. H-E-B is a retail company first, and the largest privately held company in Texas. Our customers care about full shelves, not the systems behind them, and for decades those systems delivered: rock-solid COBOL mainframes doing their job reliably, day in and day out. Reliability like that is no small thing. 2018 年我加入 H-E-B 时,进入了一个与我之前所有技术岗位截然不同的世界。H-E-B 首先是一家零售公司,也是德克萨斯州最大的私营企业。我们的顾客关心的是货架是否充足,而不是背后的系统。几十年来,这些系统表现出色:坚如磐石的 COBOL 大型机日复一日地可靠运行。这种可靠性绝非易事。
But customer expectations have shifted. Curbside pickup, home delivery, real-time inventory, in-store search, and many other tech-heavy features have really only emerged in the last 10 years, and meeting that demand means scaling supply chain operations across 435+ stores and the distribution centers that feed them. That kind of growth asks more of our core systems than they were originally designed to give, especially as the grocery business turns more digital and more competitive by the year. 但顾客的期望已经发生了变化。路边取货、送货上门、实时库存、店内搜索以及许多其他技术密集型功能,实际上都是在过去 10 年里才出现的。满足这些需求意味着要将供应链运营扩展到 435 家以上的门店及其配套的配送中心。这种增长对我们的核心系统提出了比最初设计时更高的要求,尤其是在杂货业务日益数字化且竞争日益激烈的今天。
It’s no secret that a lot of the world still runs on mainframes. There’s usually little incentive to spend the capital on a massive lift-and-shift into the cloud when current systems maintain the status quo well enough. Copying code from one machine to another is hardly the real challenge here. Usually these kinds of projects fail to deliver because they lack the bespoke institutional knowledge encoded in decades of legacy business logic. How do you take a monolithic application operating on hundreds of tables and split it out into microservices, owned and operated by their own autonomous engineering teams? It’s both a technological and political undertaking of enormous proportions, and an expensive one. Whatever product comes out on the other end, you can bet that the business owners don’t want to repeat this process ever again. 众所周知,世界上许多业务仍运行在大型机上。当现有系统能够很好地维持现状时,通常很少有动力投入大量资金进行大规模的云迁移(lift-and-shift)。将代码从一台机器复制到另一台机器并不是真正的挑战。这类项目通常失败的原因在于,它们缺乏几十年来编码在遗留业务逻辑中的定制化机构知识。你如何将一个操作数百张表的单体应用拆分为由各自自治工程团队拥有和运营的微服务?这既是一项巨大的技术工程,也是一项巨大的政治工程,而且成本高昂。无论最终产出什么产品,你都可以肯定,业务所有者绝不想再重复这个过程。
Enter the lambda
引入 Lambda
Haskell was originally pitched by consultants as the lingua franca for a new initiative to replace the largest mainframe application in the company. I came onto this new project in its infancy, ready and giddy to use Haskell on a real-world project with real-world impact. What started as an experiment grew into multiple production systems now running critical supply chain applications. Eight years on, those systems are still in production, with nearly a million lines of Haskell maintained by several teams across different domains. So there have been real successes, but also real struggles. I hope that my experience on these projects can translate into some valuable lessons for those who wonder about or may already be running Haskell programs in production. Haskell 最初是由顾问提议作为一项新计划的通用语言,旨在取代公司最大的大型机应用。我在这项新项目处于萌芽阶段时加入,准备并兴奋地在具有实际影响力的现实项目中使用 Haskell。最初的实验演变成了多个生产系统,现在运行着关键的供应链应用。八年过去了,这些系统仍在生产中运行,由不同领域的多个团队维护着近百万行的 Haskell 代码。因此,我们既取得了真正的成功,也经历了真正的挣扎。我希望我在这些项目中的经验能为那些对在生产环境中使用 Haskell 感兴趣或已经在运行 Haskell 程序的人提供一些宝贵的经验教训。
Why Haskell?
为什么选择 Haskell?
Pitching a programming language as a business solution is an uphill battle. Haskell is not known for being an enterprise language, and while it thrives in programming-language research, it lost the foothold it once had in the intro course, despite Dijkstra’s famous defense of it over Java in his letter to the UT Austin Budget Council. But “enterprise language” says more about market forces than language design. The same momentum that filled the intro course with Java fills the hiring pool and the vendor SDK lists, and nearly all of that momentum belongs to imperative languages, deemed easier to hire for, and these days, easier to prompt for. 将一种编程语言作为商业解决方案来推销是一场艰苦的战斗。Haskell 并不以“企业级语言”著称,虽然它在编程语言研究领域蓬勃发展,但它在入门课程中曾经拥有的地位已经丧失,尽管 Dijkstra 在给德克萨斯大学奥斯汀分校预算委员会的信中曾著名地为它辩护,认为它优于 Java。但“企业级语言”更多地反映了市场力量,而非语言设计本身。那种让 Java 充斥入门课程的动力,同样也充斥着招聘池和供应商 SDK 列表,而几乎所有的动力都属于命令式语言——因为它们被认为更容易招聘,而且在今天,更容易通过提示词(prompt)生成代码。
The enterprise cares not for laziness, pure functions, immutable data, or anything that weighs lambda calculus against object-oriented orthodoxy. The enterprise just wants another COBOL: a system that runs for 40 more years without null-pointer exceptions and with a lower maintenance burden. I firmly believe that Haskell fits into this niche. But it’s not trivial to translate the benefits of a souped-up polymorphic lambda calculus and software-transactional memory into a business case. 企业并不关心惰性求值、纯函数、不可变数据,也不关心任何将 Lambda 演算与面向对象正统观念进行权衡的理论。企业只是想要另一个 COBOL:一个能再运行 40 年、没有空指针异常且维护负担更低的系统。我坚信 Haskell 正好填补了这一空白。但是,将增强型多态 Lambda 演算和软件事务内存(STM)的优势转化为商业案例并非易事。
So what’s my pitch? I can tell our CTO that a Haskell application will suffer fewer classes of runtime failure by default, ruling out the whole category of bugs that imperative and dynamically typed programs encounter on a daily basis. There will still be bugs, but the ones that remain tend to be the interesting ones in our business logic, rather than null-pointer exceptions and type confusion. 那么我的推销点是什么?我可以告诉我们的 CTO,Haskell 应用默认会遭受更少类别的运行时故障,从而排除了命令式和动态类型程序每天都会遇到的那一整类 Bug。Bug 依然存在,但剩下的往往是我们业务逻辑中那些“有趣”的 Bug,而不是空指针异常和类型混淆。
In the face of multi-year strangler fig migrations of legacy systems, I can tell Haskell developers that it’s ok to make mistakes. They can iterate while the business requirements are still taking shape, because GHC gives them the tools for painless refactoring. That freedom is what lets a migration run like an agile project instead of a waterfall. The business measures results incrementally, rather than paying up front for an incorrect, crystallized product that will be abandoned in a year. 面对遗留系统长达数年的“绞杀者模式”(strangler fig)迁移,我可以告诉 Haskell 开发者:犯错没关系。他们可以在业务需求尚在形成时进行迭代,因为 GHC 为他们提供了无痛重构的工具。这种自由让迁移过程像敏捷项目一样运行,而不是像瀑布式项目。企业可以增量地衡量结果,而不是预先为一个不正确、已固化且一年后就会被废弃的产品买单。
Integrating with legacy systems is bread-and-butter work for Haskell programs. By chance do you need to parse thousands of lines of fixed-width IBM copybooks? Parsers in Haskell are best in class. A legacy system that can’t easily emit XML or JSON doesn’t have to, because its native format becomes the contract. Need to hook into old services that only offer C libraries? Haskell has one of the best foreign-function interfaces in the game. We’ve written Haskell libraries around simdjson (C++), Oracle’s ODPI-C, and IBM’s MQ, to name a few. 与遗留系统集成是 Haskell 程序的家常便饭。碰巧需要解析数千行固定宽度的 IBM Copybook 吗?Haskell 中的解析器是同类中最好的。一个无法轻易输出 XML 或 JSON 的遗留系统不必强行转换,因为其原生格式本身就可以成为契约。需要连接到只提供 C 语言库的旧服务吗?Haskell 拥有业内最好的外部函数接口(FFI)之一。我们围绕 simdjson (C++)、Oracle 的 ODPI-C 和 IBM 的 MQ 等编写了 Haskell 库,这仅举几例。
The dearth of Haskell SDKs in the wild looks like a showstopper at first. In practice, you take on the maintenance burden forever, and in exchange you own your contracts outright, avoid vendor lock-in, and never wait on an upstream maintainer to ship a fix. For critical dependencies, we’ve found that trade well worth making. Today the velocity gap is narrower than it looks, since porting your favorite Go library to Haskell is the kind of mechanical work a coding agent does well. Unfortunately, rote translations… 市面上 Haskell SDK 的匮乏起初看起来像是一个致命障碍。但在实践中,你承担了长期的维护负担,作为交换,你完全掌控了自己的契约,避免了供应商锁定,也无需等待上游维护者发布修复程序。对于关键依赖项,我们发现这种权衡非常值得。如今,开发速度的差距比看起来要小,因为将你最喜欢的 Go 库移植到 Haskell 属于编码代理(coding agent)擅长的机械性工作。遗憾的是,死记硬背式的翻译……