Leo*_*nti 5 scala monad-transformers free-monad scala-cats
我正在尝试在我的项目中开始使用免费的 monad,我正在努力让它变得优雅。
假设我有两个上下文(实际上我有更多) -Receipt而且User- 都对数据库进行了操作,我希望将它们的解释器分开并在最后一刻组合它们。
为此,我需要为每个操作定义不同的操作,并使用Coproduct.
这是我经过几天的谷歌搜索和阅读后的结果:
// Receipts
sealed trait ReceiptOp[A]
case class GetReceipt(id: String) extends ReceiptOp[Either[Error, ReceiptEntity]]
class ReceiptOps[F[_]](implicit I: Inject[ReceiptOp, F]) {
def getReceipt(id: String): Free[F, Either[Error, ReceiptEntity]] = Free.inject[ReceiptOp, F](GetReceipt(id))
}
object ReceiptOps {
implicit def receiptOps[F[_]](implicit I: Inject[ReceiptOp, F]): ReceiptOps[F] = new ReceiptOps[F]
}
// Users
sealed trait UserOp[A]
case class GetUser(id: String) extends UserOp[Either[Error, User]]
class UserOps[F[_]](implicit I: Inject[UserOp, F]) {
def getUser(id: String): Free[F, Either[Error, User]] = Free.inject[UserOp, F](GetUser(id))
}
object UserOps {
implicit def userOps[F[_]](implicit I: Inject[UserOp, F]): UserOps[F] = new UserOps[F]
}
Run Code Online (Sandbox Code Playgroud)
当我想编写程序时,我可以这样做:
type ReceiptsApp[A] = Coproduct[ReceiptOp, UserOp, A]
type Program[A] = Free[ReceiptsApp, A]
def program(implicit RO: ReceiptOps[ReceiptsApp], UO: UserOps[ReceiptsApp]): Program[String] = {
import RO._, UO._
for {
// would like to have 'User' type here
user <- getUser("user_id")
receipt <- getReceipt("test " + user.isLeft) // user type is `Either[Error, User]`
} yield "some result"
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,例如userin for comprehension 是Either[Error, User]可以理解getUser签名的类型。
我想要的是User输入或停止计算。
我知道我需要以某种方式使用EitherTmonad 转换器 or FreeT,但是经过数小时的尝试,我不知道如何组合这些类型以使其工作。
有人可以帮忙吗?如果需要更多详细信息,请告诉我。
我还在这里创建了一个最小的 sbt 项目,所以任何愿意帮助的人都可以运行它:https : //github.com/Leonti/free-monad-experiment/blob/master/src/main/scala/example/FreeMonads。斯卡拉
干杯,莱昂蒂
Freek库实现了解决您的问题所需的所有机制:
type ReceiptsApp = ReceiptOp :|: UserOp :|: NilDSL
val PRG = DSL.Make[PRG]
def program: Program[String] =
for {
user <- getUser("user_id").freek[PRG]
receipt <- getReceipt("test " + user.isLeft).freek[PRG]
} yield "some result"
Run Code Online (Sandbox Code Playgroud)
当您重新发现自己时,如果不经历余积的复杂性,自由单子之类的东西就无法扩展。如果您正在寻找一个优雅的解决方案,我建议您看看Tagless Final Interpreters。
| 归档时间: |
|
| 查看次数: |
486 次 |
| 最近记录: |