结合 EitherT 和 OptionT 的 Scalaz 错误
Scalaz error combining EitherT and OptionT
我正在做一个使用 scalaZ 的 monad 转换器 EitherT 和 OptionT 的例子,但我有一个我不明白的编译错误。
这是我的示例代码
class EitherTMonadTransformer {
case class Error(msg: String)
case class User(username: String, email: String)
def authenticate(token: String): Future[Error \/ String] = Future {
\/.right("token")
}
def getUser(username: String): Future[Option[User]] = Future {
Some(User("paul", "osmosis_paul@gmail.com"))
}
val userObj: Future[\/[Error, Nothing]] =
(for {
username <- EitherT(authenticate("secret1234"))
user <- OptionT(getUser(username))
} yield user.username).run
@Test
def eitherTAndOptionT(): Unit = {
println(userObj)
}
}
编译错误说
Error:(32, 12) type mismatch;
found : scalaz.OptionT[scala.concurrent.Future,String]
required: scalaz.EitherT[scala.concurrent.Future,EitherTMonadTransformer.this.Error,?]
user <- OptionT(getUser(username))
知道哪里出了问题吗?
此致。
问题在于,在一个 for 表达式中,您不能随意混合和匹配不同的 monad。在这种特殊情况下,您试图将 OptionT
monad 与 EitherT
monad 混合。请记住,monad 转换器本身就是 monad。编译器一看到这一行 username <- EitherT(authenticate("secret1234"))
,就会将 EitherT
推断为 for 表达式中使用的 monad,并期望它用于其余部分。一种可能的解决方案是更改 getUser
方法返回的类型,例如:
def getUser(username: String): Future[Error \/ User] = Future {
\/.right(User("paul", "osmosis_paul@gmail.com"))
}
当然,您也必须按如下方式更改 for 表达式:
val userObj: Future[\/[Error, String]] =
(for {
username <- EitherT(authenticate("secret1234"))
user <- EitherT(getUser(username))
} yield user.username).run
这样类型对齐并且编译器会很乐意接受它们。
我正在做一个使用 scalaZ 的 monad 转换器 EitherT 和 OptionT 的例子,但我有一个我不明白的编译错误。
这是我的示例代码
class EitherTMonadTransformer {
case class Error(msg: String)
case class User(username: String, email: String)
def authenticate(token: String): Future[Error \/ String] = Future {
\/.right("token")
}
def getUser(username: String): Future[Option[User]] = Future {
Some(User("paul", "osmosis_paul@gmail.com"))
}
val userObj: Future[\/[Error, Nothing]] =
(for {
username <- EitherT(authenticate("secret1234"))
user <- OptionT(getUser(username))
} yield user.username).run
@Test
def eitherTAndOptionT(): Unit = {
println(userObj)
}
}
编译错误说
Error:(32, 12) type mismatch;
found : scalaz.OptionT[scala.concurrent.Future,String]
required: scalaz.EitherT[scala.concurrent.Future,EitherTMonadTransformer.this.Error,?]
user <- OptionT(getUser(username))
知道哪里出了问题吗?
此致。
问题在于,在一个 for 表达式中,您不能随意混合和匹配不同的 monad。在这种特殊情况下,您试图将 OptionT
monad 与 EitherT
monad 混合。请记住,monad 转换器本身就是 monad。编译器一看到这一行 username <- EitherT(authenticate("secret1234"))
,就会将 EitherT
推断为 for 表达式中使用的 monad,并期望它用于其余部分。一种可能的解决方案是更改 getUser
方法返回的类型,例如:
def getUser(username: String): Future[Error \/ User] = Future {
\/.right(User("paul", "osmosis_paul@gmail.com"))
}
当然,您也必须按如下方式更改 for 表达式:
val userObj: Future[\/[Error, String]] =
(for {
username <- EitherT(authenticate("secret1234"))
user <- EitherT(getUser(username))
} yield user.username).run
这样类型对齐并且编译器会很乐意接受它们。