【发布时间】:2021-05-26 23:13:09
【问题描述】:
问题: 链接多个 Either 返回函数,其中 Left 都是从公共密封特征 InternalError 继承的失败。但是,编译器抱怨 chain 正在返回 Either[_,Success] 而不是 Either[InternalError, Success]。
这是执行链接的代码:
import scala.language.implicitConversions
object EitherExtension {
implicit class AndThenEither[A,B](val e: Function1[A,Either[_,B]]) {
//get ability to chain/compose functions that return aligning Eithers
def andThenE[C](f:Function1[B, Either[_,C]]): Function1[A, Either[_,C]] = {
(v1: A) => e.apply(v1).flatMap(b => f.apply(b))
}
}
}
正如 cmets 中所指出的,这会丢弃 Left 的类型。如果我在下面更改它,它将无法正常工作,因为最终输出可以是Either[X|Y, C] 类型,它解析为Either[_,C],我又回到了第一格。
implicit class AndThenEither[A,B,X](val e: (A) => Either[X, B]) {
def andThenE[C,Y](f:(B) => Either[Y, C]): (A) => Either[_, C] = {
(v1: A) => e.apply(v1).flatMap(b => f.apply(b))
}
}
这是显示类型对齐的组合失败的示例:
import EitherExtension._
object AndThenComposition {
//sample type definitions of failure responses
sealed trait InternalError
case class Failure1() extends InternalError
case class Failure2() extends InternalError
//sample type definitions
case class Id(id: Int)
case class Stuff()
//sample type definitions of successful responses
case class Output1()
case class Output2()
case class InputRequest()
val function1: (InputRequest) => Either[Failure1, Output1] = ???
val function2: (Output1) => Either[Failure2, Output2] = ???
def doSomething(s:Id, l:List[Stuff]): Either[InternalError, Output2] = {
val pipeline = function1 andThenE function2
pipeline(InputRequest()) //Why is this of type Either[_, Output2]
}
}
我错过了什么?我怎样才能让返回类型 not 是 Either[Any, Output2] 而是基本/密封特征?这可以通用吗?
【问题讨论】:
-
好吧,你的
andThenE丢弃了 Left 的类型......所以不知道为什么你甚至问它为什么这样做,你告诉它这样做。 -
我明白你的意思——但我怎样才能让它不这样做呢?
andThenE的输出结果总是Either[_,C],因为错误可能来自链中的 previous 函数或这个函数,两者都可以是不同的类型。我不想在泛型函数中声明错误的 type,因此使用andThenE签名。 -
@LuisMiguelMejíaSuárez - 更新了问题以更好地反映问题的根源。
-
@LuisMiguelMejíaSuárez - 请您发表评论/链接一个答案,以便我接受吗?它确实解决了我的问题并使编译成功。如果出现新问题,我会问一个新/后续问题????
标签: scala