Iga*_*nik 3 functional-programming scala free-monad scala-cats
我有一些"遗留的"Scala代码(类似Java),它可以进行一些数据访问.有一个装饰器跟踪DAO方法的使用(收集指标),如下所示:
class TrackingDao(tracker: Tracker) extends Dao {
def fetchById(id: UUID, source: String): Option[String] = {
tracker.track("fetchById", source) {
actualFetchLogic(...)
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
我试图把它塑造成一个免费的monad.我为DAO操作定义了以下代数:
sealed trait DBOp[A]
case class FetchById(id: UUID) extends DBOp[Option[String]]
...
Run Code Online (Sandbox Code Playgroud)
我看到两个选择:
a)我可以制作两个解释器DBOp,一个执行实际数据访问,另一个执行跟踪,并将它们组合在一起或者
b)我使跟踪成为一个显式代数,并使用Coproduct在同一个for组合中使用它们或者
c)完全不同的东西!
第一个选项看起来更像是一个"装饰器"方法,它与DBOp第二个选项相关,第二个选项是更通用的解决方案,但需要明确地调用"跟踪"代数.
另外,请注意source原始fetchById呼叫上的参数:它仅用于跟踪.我更愿意从API中删除它.
这是实际问题:如何建模跟踪?
从您的问题来看并不完全清楚,但如果跟踪是一种环境影响,当您执行数据库访问时它应该"发生"并且source仅仅是用于跟踪目的的参数,您可能根本不必用您的免费语言提及它.你可以使用你现在拥有的ADT并解释(Tracker, Source, OtherStuff) => IO[A]为例如,所以你得到的是一个函数,它会产生一个程序来进行数据库访问,一旦你给它一个Tracker源和你需要的任何其他东西(例如数据库连接),并且跟踪实现完全是解释器的私有.这使您可以编写数据库程序而无需考虑跟踪.
如果在另一方面,你就需要谈谈你的业务逻辑跟踪那么我们可能需要什么这将意味着有多个详细信息,TrackerS和sourceS和他们是如何引进和使用.可能需要联合产品或扩展语言或嵌套语言来处理您需要表达的内容.