我的代码
open class Fail(override val message: String, override val cause: Throwable?) : RuntimeException(message, cause)
data class ValidationFail(override val message: String, override val cause: Throwable?) : Fail(message, cause)
以后会在那里定义更多的失败
我有两个功能
fun fun1(): Either<out Fail, A>
fun fun2(a: A): Either<out Fail, B>
当我尝试像这样调用它们时 fun1().flatMap{fun2(it)}
我得到了
Type mismatch: inferred type is (A!) -> Either<out Fail, B> but ((A!) -> Nothing)! was expected. Projected type Either<out Fail, A> restricts use of public final fun <U : Any!> flatMap(p0: ((R!) -> Either<L!, out U!>!)!): Either<L!, U!>! defined in io.vavr.control.Either
来自 vavr 的代码:
default <U> Either<L, U> flatMap(Function<? super R, ? extends Either<L, ? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (isRight()) {
return (Either<L, U>) mapper.apply(get());
} else {
return (Either<L, U>) this;
}
}
我猜 o 有这个错误是因为 flatMap 定义中有 L
而不是 ?扩展 L
有什么解决方法吗?
最佳答案
在您的特定情况下,您可以通过从 fun1
和 fun2
返回类型中删除 out
差异来使其编译。 You shouldn't use wildcard types as return types anyway .
但是,如果您以这种方式定义了 fun1
和 fun2
,那将无济于事:
fun fun1(): Either<ConcreteFail1, A>
fun fun2(a: A): Either<ConcreteFail2, B>
用 替换
也无济于事,因为 L
? flatMap
签名中的 extends LConcreteFail2
不是 ConcreteFail1
的子类型。问题是 Either
应该是协变的,但在 Java 中没有声明位点差异这样的东西。虽然有一个使用 Either#narrow
的解决方法方法:
Either.narrow<Fail, A>(fun1()).flatMap { Either.narrow(fun2(it)) }
当然,它看起来很奇怪,必须提取到一个单独的扩展函数中:
inline fun <L, R, R2> Either<out L, out R>.narrowedFlatMap(
crossinline mapper: (R) -> Either<out L, out R2>
): Either<L, R2> = narrow.flatMap { mapper(it).narrow }
narrow
是:
val <L, R> Either<out L, out R>.narrow: Either<L, R> get() = Either.narrow(this)
我认为 Vavr 没有提供它自己的 narrowedFlatMap
因为这个方法需要使用通配符接收器类型,所以它不能是一个成员方法,必须是一个静态的,它打破了操作流水线的所有可读性:
narrowedFlatMap(narrowedFlatMap(narrowedFlatMap(fun1()) { fun2(it) }) { fun3(it) }) { fun4(it) }
但由于我们使用 Kotlin,我们也可以管道化静态(扩展)函数:
fun1().narrowedFlatMap { fun2(it) }.narrowedFlatMap { fun3(it) }.narrowedFlatMap { fun4(it) }
关于kotlin - 如何使用带左方差注释的 flatMap vavr Either,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58841465/