Scala 将所有类型提升到monad变压器中

Scala 将所有类型提升到monad变压器中,scala,monad-transformers,scala-cats,Scala,Monad Transformers,Scala Cats,我有这3个单子变形金刚 type T[A] = OptionT[Future, A] type E[A] = EitherT[Future, String, A] type P[A] = OptionT[E, A] 我想将相应的完整类型(即确切的对应类型)提升到这些类型中。所以对于T,我想将Future[Option[Int]]提升到它里面。对于E,我想提升Future(或者[String,Int]),对于P,我想提升Future(或者[String,Option[Int]]) 我写了这段代码

我有这3个单子变形金刚

type T[A] = OptionT[Future, A]
type E[A] = EitherT[Future, String, A]
type P[A] = OptionT[E, A]
我想将相应的完整类型(即确切的对应类型)提升到这些类型中。所以对于T,我想将Future[Option[Int]]提升到它里面。对于E,我想提升Future(或者[String,Int]),对于P,我想提升Future(或者[String,Option[Int]])

我写了这段代码并编译了它。除了我需要一个更简洁的方法来实现同样的目标

val x : T[Int] = OptionT(Future(Option(10)))
val y : E[Int] = EitherT(Future(Right(10).asInstanceOf[Either[String, Int]]))
val z : P[Int] = OptionT(EitherT(Future(Right(Option(10)).asInstanceOf[Either[String, Option[Int]]])))
我正在使用Cats 1.1.0和Scala 2.12.3

这件事很烦人。但是如果我把最后一行改成

val z : P[Int] = OptionT(EitherT(Future(Right(Option(10)))))
我得到这个编译器错误

[info] Compiling 1 Scala source to 
[error] /Users//code/dallasscalacats/src/main/scala/com//Transformers.scala:32: no type parameters for method apply: (value: F[Either[A,B]])cats.data.EitherT[F,A,B] in object EitherT exist so that it can be applied to arguments (scala.concurrent.Future[scala.util.Right[Nothing,Option[Int]]])
[error]  --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error]  found   : scala.concurrent.Future[scala.util.Right[Nothing,Option[Int]]]
[error]  required: ?F[Either[?A,?B]]
[error]     val z : P[Int] = OptionT(EitherT(Future(Right(Option(10)))))
[error]                              ^
[error] /Users//code/dallasscalacats/src/main/scala/com//Transformers.scala:32: type mismatch;
[error]  found   : scala.concurrent.Future[scala.util.Right[Nothing,Option[Int]]]
[error]  required: F[Either[A,B]]
[error]     val z : P[Int] = OptionT(EitherT(Future(Right(Option(10)))))
[error]                                            ^
[error] /Users//code/dallasscalacats/src/main/scala/com//Transformers.scala:32: type mismatch;
[error]  found   : cats.data.EitherT[F,A,B]
[error]  required: com.abhi.Transformers.E[Option[Int]]
[error]     (which expands to)  cats.data.EitherT[scala.concurrent.Future,String,Option[Int]]
[error]     val z : P[Int] = OptionT(EitherT(Future(Right(Option(10)))))
[error]                                     ^
[error] three errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 0 s, completed Jul 11, 2018 9:46:21 PM
>

尝试为右侧提供类型参数:

val z : P[Int] = OptionT(EitherT(Future(Right[String,Option[Int]](Option(10)))))

如果没有类型参数,当您执行
Right(1)
scala推断
时,请尝试为Right提供类型参数:

val z : P[Int] = OptionT(EitherT(Future(Right[String,Option[Int]](Option(10)))))

如果没有类型参数,当您执行
Right(1)
scala推断
或[Nothing,Int]
时,您可以使用import cats.implicits的隐式方法 然后你可以写一些像

val z: P[Int] = OptionT(EitherT(Future(10.some.asRight[String])))
当然,你也可以自己写

implicit class EitherFuture[A, B](val e: Future[A Either B]) extends AnyVal {
  def asEitherT: EitherT[Future, A, B] = EitherT(e)
}

implicit class OptionEitherT[A](val e: EitherT[Future, String, Option[A]]) extends AnyVal {
  def asOptionT = OptionT(e)
}

val zz: P[Int] = Future(10.some.asRight[String]).asEitherT.asOptionT

您可以使用implicits方法导入cats.implicits.\uu
然后你可以写一些像

val z: P[Int] = OptionT(EitherT(Future(10.some.asRight[String])))
当然,你也可以自己写

implicit class EitherFuture[A, B](val e: Future[A Either B]) extends AnyVal {
  def asEitherT: EitherT[Future, A, B] = EitherT(e)
}

implicit class OptionEitherT[A](val e: EitherT[Future, String, Option[A]]) extends AnyVal {
  def asOptionT = OptionT(e)
}

val zz: P[Int] = Future(10.some.asRight[String]).asEitherT.asOptionT

还是很冗长。没有更好的办法了吗?还是很冗长。没有更好的办法了吗?很酷!让我们看看是否有更多的答案。否则我很乐意标记这个。请确保
扩展AnyVal
,以避免隐式类的额外包装分配。@YuvalItzchakov感谢您的评论。更新了答案我还有最后一个问题。一切正常。但是如果我为{x@known尽管这有点离题,
foreach
相当于没有
yield
for
语句。我可以运行您粘贴的代码。因此检查实际代码的语法。非常酷!让我们看看是否有更多答案。否则我很乐意标记此答案。确保
扩展AnyVal
以避免错误隐式类的额外包装分配。@YuvalItzchakov感谢您的评论。更新了答案我还有最后一个问题。一切正常。但是如果我为{x@known尽管这有点离题,
foreach
相当于没有
yield
for
语句。我可以运行您粘贴的代码。因此请检查实际代码的语法。