斯卡拉(Scala),猫-如何使用IO(或其他monad)和两者之一创建无标签最终实现?

我创建了一个简单的trait及其实现:

trait UserRepositoryAlg[F[_]] {

  def find(nick: String): F[User]

  def update(user: User): F[User]
}

class UserRepositoryInterpreter extends UserRepositoryAlg[Either[Error,*]] {
  override def find(nick: String): Either[Error,User] = for {
    res <- users.find(user => user.nick == nick).toRight(UserError)
  } yield res

  override def update(user: User): Either[Error,User] = for {
    found <- users.find(u => u.nick == user.nick).toRight(UserError)
    updated = found.copy(points = found.points + user.points)
  } yield updated
}

在这里,我想使用EitherEitherT来“捕获”错误,但是我也想使用IOFuture作为主要的monad。在主类中,我创建了对此实现的调用:

 object Main extends App {

  class Pointer[F[_] : Monad](repo: UserRepositoryAlg[F]) {
    def addPoints(nick: String): EitherT[F,Error,User] = {
      for {
        user <- EitherT.right(repo.find(nick))
        updated <- EitherT.right(repo.update(user))
      } yield Right(updated)
    }
  }
  val pointer = new Pointer[IO](new UserRepositoryInterpreter{}).addPoints("nick")
}

但是在创建pointer的行中,IntelliJ向我显示了一个错误:Type mismatch - required: UserRepositoryAlg[F],found: UserRepositoryInterpreter,但我不明白为什么。我使用Pointer作为F[_]创建了IO类,并想使用UserRepositoryAlg[F]的实现。如何解决此问题,或者在这种情况下有什么好的做法?如果我想实现以下目标:IO[Either[Error,User]]EitherT[IO,User]

我试图将class UserRepositoryInterpreter extends UserRepositoryAlg[Either[Error,*]]改成class UserRepositoryInterpreter[F[_]] extends UserRepositoryAlg[F[Either[Error,*]]]之类的东西,但这无济于事。

编辑: 我发现了如何使用F[Either[Error,User]]来转换Applicative[F]来返回A => F[A]

class UserRepositoryInterpreter[F[_] : Applicative] extends UserRepositoryAlg[F[Either[Error,*]]] {
  override def find(nick: String): F[Either[Error,User]] = for {
    res <- Applicative[F].pure(users.find(user => user.nick == nick).toRight(UserError))
  } yield res

  override def update(user: User): F[Either[Error,User]] = for {
    found <- Applicative[F].pure(users.find(u => u.nick == user.nick).toRight(UserError))
    updated = Applicative[F].pure(found.map(u => u.copy(points = u.points + user.points)))
  } yield updated
}

但是我的主要功能仍然有问题,因为我无法获得Right的{​​{1}}值:

Either

这里 def addPoints(nick: String): EitherT[F,User] = { for { user <- EitherT.liftF(repo.find(nick)) updated <- EitherT.rightT(repo.update(user)) } yield Right(updated) } updated <- EitherT.rightT(repo.update(user))user,但我只需要通过Either[Error,User]。所以我尝试做类似的事情: User并通过它,但这也无济于事。我应该如何看待这个价值?

linus2wan 回答:斯卡拉(Scala),猫-如何使用IO(或其他monad)和两者之一创建无标签最终实现?

document_id|user_id1|user_id2| -----------|--------|--------| 100|10 |20 | 100|20 | | 200|10 |20 | 200|20 | | 300|10 |20 | 300|20 | | 描述了您的主要效果。从理论上讲,您可以使用任何monad(甚至更高类型的monad),但实际上,最好的选择是monad,它允许您像F[_]cats-effect那样暂停执行。 / p>

您的问题是您试图使用Future作为主要效果,但是对于IO,您将UserRepositoryInterpreter设置为Either

您应该做的只是参数化F,您可以选择效果单声道。如果要同时使用UserRepositoryInterpreterEither来处理错误,请同时使用monad堆栈F

示例解决方案:

F[Either[Error,User]]
本文链接:https://www.f2er.com/3138319.html

大家都在问