gpt4 book ai didi

scala - 使用哪个 Monad Transformer?

转载 作者:行者123 更新时间:2023-12-04 23:15:56 33 4
gpt4 key购买 nike

我正在尝试编写下面的验证函数,以便在遇到第一个错误后停止验证。 three的返回类型与其他功能不同。我使用哪个 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, 7) type mismatch;
found : scalaz.EitherT[scala.concurrent.Future,Int,String]
required: scalaz.\/[?,?]
e3 <- EitherT(three(a))
^

最佳答案

在这种情况下,您可以采用两种通用方法。第一种是让所有方法返回您知道将使用的堆栈(在本例中为 EitherT[Future, Int, ?] ),或者您可以让每个单独的方法返回最准确地捕获其自身效果的类型,然后引发当你组合它们时,你会得到适当的值。

如果您确切地知道该用法将是什么样子,则第一种方法可以使使用在语法上更加方便,但后一种方法更灵活,在我看来通常是更好的选择。在你的情况下,它看起来像这样:

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, Int, 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)

如果由于某种原因你有一个普通的旧 Future您想在 for 中使用的- 理解,你可以把它提升到 EitherT[Future, String, A].liftM[EitherT[?[_], String, ?]] .

(请注意,此方法可能不是非常有用,因为它永远不会成功(字符串不能同时等于 "one""two""three" ),但至少是组合行得通。)

关于如何更一般地选择 monad 转换器堆栈:您只需将类型翻过来,以便 Future[Disjunction[Int, ?]]变成 EitherT[Future, Int, ?]等。在这种情况下,特别是 Future没有 monad 转换器(它是不可遍历的,并且不可能在不阻塞的情况下实现 FutureT),所以你知道它必须在内部进行,无论如何。

关于scala - 使用哪个 Monad Transformer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42290243/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com