在 Production Haskell 中,Matt Parsons 有一个标题为“嵌入,不要堆叠”的部分。他在其中提到了以下内容:
在应用程序类型中添加大量 monad 转换器是错误的。一个 monad 转换器可满足您可能关心的每一种效果。
建议的一般模式是将内容嵌入到您的
类型中。App
分解代码,使效果彼此独立运行,可以更轻松地理解和阅读代码。
但他从未明确定义“嵌入”的含义。
这个术语有通用的定义吗?type App a = FooT (BarT (BazT IO a))
不是一个好主意,因为它意味着任何返回
App a
的函数都可以执行任意数量的四种不同效果:它可能执行 Foo、Bar、Baz、IO 或所有这些。相反,有一个更小的
App
类型,可能会融入一两个真正的核心效果,比如 type App a = Reader (Config, DbHandle) a
然后需要使用一些其他效果的功能可以在
a
部分显示这些效果:
debitAccountBy :: AccountNumber -> Money -> App (WriteToDb Money)
通过这种方式,您可以使用类型系统将程序分成效率较高和效率较低的部分,而不是让所有函数都能够执行各种效果。