Dependency injection Arrow KT:依赖注入的读卡器Monad与@extension

Dependency injection Arrow KT:依赖注入的读卡器Monad与@extension,dependency-injection,reader-monad,arrow-kt,Dependency Injection,Reader Monad,Arrow Kt,我自己读过这篇文章,我也得到了这篇文章。似乎两者都以不同的方式处理了依赖注入的思想。(还是我错了?) 我真的很困惑,我是否理解整个过程,以及它与所讨论的简单依赖性注入的关系 有人能帮我理解这两件事吗?在一个项目中,我会根据具体情况同时使用这两种方法吗?您的疑问是可以理解的,因为是的,这两种方法都有相同的结果:在整个调用堆栈中隐式地传递依赖项,所以您不必在每个级别上都显式地传递它们。使用这两种方法,您将从外部边缘传递依赖项一次,仅此而已 假设有函数a()、b()、c()和d(),并且假设每个函数调

我自己读过这篇文章,我也得到了这篇文章。似乎两者都以不同的方式处理了
依赖注入的思想。(还是我错了?)

我真的很困惑,我是否理解整个过程,以及它与所讨论的
简单依赖性注入的关系


有人能帮我理解这两件事吗?在一个项目中,我会根据具体情况同时使用这两种方法吗?

您的疑问是可以理解的,因为是的,这两种方法都有相同的结果:在整个调用堆栈中隐式地传递依赖项,所以您不必在每个级别上都显式地传递它们。使用这两种方法,您将从外部边缘传递依赖项一次,仅此而已

假设有函数a()、b()、c()和d(),并且假设每个函数调用下一个函数:a()->b()->c()->d()。这是我们的节目

如果您没有使用上述任何机制,并且在d()中需要一些依赖项,那么最终会在每个级别上转发依赖项(我们称之为ctx):

a(ctx) -> b(ctx) -> c(ctx) -> d(ctx)
而在使用上述两种方法中的任何一种后,情况如下:

a(ctx) -> b() -> c() -> d()
但是,这是需要记住的重要一点,您可以在这些函数中的每个函数的范围内访问依赖项。这是可能的,因为使用所描述的方法,您可以启用一个封闭上下文,该上下文在每个级别上自动转发它们,并且每个函数都在其中运行。因此,在该上下文中,函数可以看到这些依赖项

读者:这是一种数据类型。我鼓励您阅读并尝试理解此术语表,其中解释了数据类型,因为这两种方法之间的差异需要了解什么是类型类和数据类型,以及它们是如何协同工作的:

总之,数据类型表示程序数据的上下文。在本例中,Reader代表需要运行某些依赖项的计算。例如,类似(D)->a的计算。由于它的flatMap/map/及其其他函数及其编码方式,D将在每个级别上隐式传递,并且由于您将每个程序函数定义为读卡器,因此您将始终在读卡器上下文中操作,从而访问所需的依赖项(ctx)。即:

请注意,扩展函数接收器是一个参数,如果没有扩展函数支持,您需要在每次调用时手动将其作为附加函数参数传递,因此这样就形成了函数运行所需的依赖项或“上下文”。通过这种方式理解这些,并理解Kotlin如何解释扩展函数,接收器不需要在每个级别上手动转发,只需传递到入口边缘:

ctx.a() -> b() -> c() -> d()
B、 c、c和d将被隐式调用,而无需通过接收器显式调用每个级别的函数,因为每个函数都已在该上下文中运行,因此它可以自动访问其属性(依赖项)

因此,一旦我们了解了这两种方法,我们就需要选择一种或任何其他DI方法。这是相当主观的,因为在函数世界中,还有其他注入依赖项的替代方法,比如依赖类型类及其编译时解析的无标记最终方法,或者在Arrow中仍然不可用但很快就会出现的EnvIO(或等效替代方法)。但我不想让你更困惑。在我看来,与IO等其他常见数据类型相结合,阅读器有点“嘈杂”,我通常采用无标记的最终方法,因为这些方法允许保留由注入类型类确定的程序约束,并依赖IO运行时完成程序


希望这有点帮助,否则请放心再问一次,我们会回来回答您的疑问是可以理解的,因为是的,两种方法都有相同的结果:在整个调用堆栈中隐式地传递依赖项,所以您不需要在每个级别上显式地传递它们。使用这两种方法,您将从外部边缘传递依赖项一次,仅此而已

假设有函数a()、b()、c()和d(),并且假设每个函数调用下一个函数:a()->b()->c()->d()。这是我们的节目

如果您没有使用上述任何机制,并且在d()中需要一些依赖项,那么最终会在每个级别上转发依赖项(我们称之为ctx):

a(ctx) -> b(ctx) -> c(ctx) -> d(ctx)
而在使用上述两种方法中的任何一种后,情况如下:

a(ctx) -> b() -> c() -> d()
但是,这是需要记住的重要一点,您可以在这些函数中的每个函数的范围内访问依赖项。这是可能的,因为使用所描述的方法,您可以启用一个封闭上下文,该上下文在每个级别上自动转发它们,并且每个函数都在其中运行。因此,在该上下文中,函数可以看到这些依赖项

读者:这是一种数据类型。我鼓励您阅读并尝试理解此术语表,其中解释了数据类型,因为这两种方法之间的差异需要了解什么是类型类和数据类型,以及它们是如何协同工作的:

总之,数据类型表示程序数据的上下文。在本例中,Reader代表需要运行某些依赖项的计算。例如,类似(D)->a的计算。由于它的flatMap/map/及其其他函数及其编码方式,D将在每个级别上隐式传递,并且由于您将每个程序函数定义为读卡器,因此您将始终在读卡器上下文中操作,从而访问所需的依赖项(ctx)。即:

请注意,扩展功能接收器是