scala – 使用哪种Monad变压器?
发布时间:2020-12-16 09:51:50 所属栏目:安全 来源:网络整理
导读:我正在尝试编写下面的验证函数,以便在遇到第一个错误后停止验证.三种返回类型与其他功能不同.我使用哪个monad变换器来编译这段代码? import scalaz._import Scalaz._import scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.glo
我正在尝试编写下面的验证函数,以便在遇到第一个错误后停止验证.三种返回类型与其他功能不同.我使用哪个monad变换器来编译这段代码?
import scalaz._ import Scalaz._ import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global def one(a : String): Disjunction[Int,String] = a == "one" match { case true => /-("one") case false => -/(2) } def two(a : String): Disjunction[Int,String] = a == "two" match { case true => /-("two") case false => -/(3) } def three(a : String): Future[Disjunction[Int,String]] = Future (a == "three") map { case true => /-("three") case false => -/(4) } def validate(a : String) = for { e1 <- one(a) e2 <- two(a) e3 <- EitherT(three(a)) } yield (e1 |+| e2 |+| e3) 编译错误: Error:(27,7) type mismatch; found : scalaz.EitherT[scala.concurrent.Future,Int,String] required: scalaz./[?,?] e3 <- EitherT(three(a)) ^ Error:(66,?] e3 <- EitherT(three(a)) ^ 解决方法
在这种情况下,您可以采取两种通用方法.第一个是让你的所有方法返回你知道你将要使用的堆栈(在这种情况下是EitherT [Future,?]),或者你可以让每个单独的方法返回最准确捕获其自身效果的类型,然后在撰写时提高你得到的值.
如果你确切地知道这种用法会是什么样子,那么第一种方法可以使语法在语法上更方便,但后一种方法更灵活,在我看来通常是更好的选择.在你的情况下,它看起来像这样: import scalaz._,Scalaz._ import scala.concurrent.Future import scala.concurrent.ExecutionContext.Implicits.global def one(a: String): Disjunction[Int,String] = (a == "one").either("one").or(2) def two(a: String): Disjunction[Int,String] = (a == "two").either("two").or(3) def three(a: String): EitherT[Future,String] = EitherT( Future(a == "three").map(_.either("three").or(4)) ) def validate(a: String) = for { e1 <- EitherT.fromDisjunction[Future](one(a)) e2 <- EitherT.fromDisjunction[Future](two(a)) e3 <- three(a) } yield (e1 |+| e2 |+| e3) 然后: scala> validate("one").run.foreach(println) -/(3) scala> validate("x").run.foreach(println) -/(2) 如果出于某种原因,你想要在for-comprehension中使用一个普通的Future,你可以用.liftM [EitherT [?[_],String,?]将它提升到EitherT [Future,A]中. ]. (注意,这种方法可能不是非常有用,因为它永远不会成功(一个字符串不能同时等于“一”,“两个”和“三个”),但至少组成工作了.) 关于如何更普遍地选择monad变换器堆栈:你只需将类型转换为内部,以便Future [Disjunction [Int,?]]成为EitherT [Future,?]等.具体来说,Future不会有一个monad变换器(它不可穿越,不可能无阻塞地实现FutureT),所以你知道它必须在内部,无论如何. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |