当前位置: 首页 > 知识库问答 >
问题:

如何在带左方差注释的情况下平面映射vavr

班经亘
2023-03-14

我的代码

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)

将来将在此处定义更多故障

我有2个功能

fun fun1(): Either<out Fail, A>
fun fun2(a: A): Either<out Fail, B>

当我尝试像这样调用它们时fun1()。平面图{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;
    }
}

我想是因为在平面图定义中有L而没有这个错误吧?扩展L

有什么解决方法吗?

共有1个答案

勾向文
2023-03-14

在您的特定情况下,可以通过从返回类型中删除方差来编译它。无论如何,您不应该使用通配符类型作为返回类型。

但是如果您以这种方式定义了fun1fun2,那就没用了:

fun fun1(): Either<ConcreteFail1, A>
fun fun2(a: A): Either<ConcreteFail2, B>

L替换为?扩展L平面图签名中也没有帮助,因为ConcreteFail2不是ConcreteFail1的子类型。问题是要么应该是协变的,但在Java中没有声明站点差异这样的东西。尽管有使用要么#窄方法的解决方法:

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 }

其中是:

val <L, R> Either<out L, out R>.narrow: Either<L, R> get() = Either.narrow(this)

我认为Vavr没有提供自己的窄化平台映射,因为此方法需要使用通配符接收器类型,所以它不能是成员方法,必须是静态方法,这会破坏操作管道的所有可读性:

narrowedFlatMap(narrowedFlatMap(narrowedFlatMap(fun1()) { fun2(it) }) { fun3(it) }) { fun4(it) }

但由于我们使用Kotlin,我们也可以将静态(扩展)函数管道化:

fun1().narrowedFlatMap { fun2(it) }.narrowedFlatMap { fun3(it) }.narrowedFlatMap { fun4(it) }
 类似资料:
  • TL;DR:将@webservlet(“/find-customers”)放在servlet(通过Tomcat 7部署)的开头并不是将servlet映射到host:port/webproject/find-customers中,即使servlet位于src文件夹中。

  • 问题内容: 我想解组一个包含数据集合的xml文件,像这样 我们知道这可以通过两个类完成:人员,使用Castor的人员,JAXB或其他框架。 但是,如果不编写收集类的Persons怎么办? 问题答案: 寻找一种方法来告诉Castor您希望它生成一个Person实例。 http://www.castor.org/how-to-map-a-list-at- root.html

  • 问题内容: 在本文http://www.jroller.com/eyallupu/entry/hibernate_the_any_annotation中,以及在此问题中,如何使用与Hibernate @Any相关的注释?,说明了如何使用@Any批注。但是我如何才能借到每张DVD / VHS / BOOK?如何在DVD / VHS / BOOK上映射定义? 问题答案: 我不 认为 这是受支持的,并且

  • 问题内容: 我正在使用@cacheable注解缓存函数的结果。我有3个不同的缓存,每个缓存的关键是当前登录的用户的用户ID,该用户ID与方法中的参数连接在一起。在某个事件中,我想逐出所有具有以该特定用户ID开头的键的缓存条目。例如 : 我希望缓存逐出注释为: 但是当我尝试实现这一点时,它给了我一个错误: 什么是实现此目的的正确方法? 问题答案: 每个操作所有Spring Cache批注(即,等)都

  • 我试图了解DI在我们的代码库(Kotlin)中是如何使用的。我们正在使用googleguice进行依赖注入。 下面是一个示例类: 在模块类中: DepB类别: 据我所知,对于用< code>@Inject注释的变量,Google Guice会使用模块类来解决这些依赖关系。所以< code>DepA对象的注入方式是有意义的。 但是呢?我们如何能够在不指定任何位置的情况下注入DepB?