【问题标题】:Why isn't Vavr Either is recognizing the parameter to map() function?为什么 Vavr Either 不能识别 map() 函数的参数?
【发布时间】:2019-05-08 04:14:23
【问题描述】:

我正在用神奇的 vavr 库(0.9.2)弄脏我的手。

这是一个代码 sn-p,旨在收集 Either

    Either<Tuple2<Enum<ReportByTeamExecutionErrors>,String>, List<MayurDAO>> payloadPreparationResult =
    new ReportByTeamCriteriaSchemaChecker("./json/schema/REQ_ReportByTeam_Schema.json")
    .validateSchema(payLoad) // payload is JSON and is a paramter to this holding function
.map(JsonPOJOBidirectionalConverter::pojofyCriteriaAllFieldsTeam)
.map((e) -> {
        CriteriaTeamAllFieldsValidator validator =  new CriteriaTeamAllFieldsValidator(e.right().get());
        return(validator.validate());
 })
 .map((e) -> retrieveRecordsAsPerCriteria(e.right().get())) // compiler doesn't approve of this line!!
 ;

retrieveRecordsAsPerCriteria 方法是这样定义的:

private Either<Tuple2<Enum<ReportByTeamExecutionErrors>,String>, List<MayurDAO>>
    retrieveRecordsAsPerCriteria(CriteriaAllFieldsTeam criteriaAllFieldsTeam) {

        Optional<List<MayurDAO>> retrievedRecords = new MayurModel().retrieveRecords(criteriaAllFieldsTeam);

        return( (retrievedRecords.isPresent())
                ? (Either.right(retrievedRecords.get()))
                : Either.left(
                        Tuple.of(
                             ReportByTeamExecutionErrors.NO_RECORDS_FOUND_TO_MATCH_CRITERIA,
                             "No records have been found, which match the criteria passed"
                        )
                       )
            );
    }

编译器在抱怨:

./com/myApp/application/ReportByTeamResource.java:58:错误: 不兼容的类型:无法推断类型变量 L,R .map((e) -> retrieveRecordsAsPerCriteria(e.right().get())); ^ (实际参数列表和形式参数列表的长度不同)其中 L,R 是类型变量: L 扩展在方法 right(R) 中声明的对象 R extends Object 声明在方法 right(R) 1 错误

列表来自 java.util.List。

我无法理解问题的根源。类型应该很容易推断出来,或者我认为是这样。

直到这条令人反感的线之前,IntelliJ 似乎都可以接受转换!然而,在那一行中,类型参数 U 是不可破译的。 由于某种原因,有人可以将我推到我看不到的路径吗?

【问题讨论】:

  • 看起来很像一些带有嵌套 Eithers 的复杂类型。可以使您的 sn-p 编译的方法是将最终的 map 替换为 flatMap。但也许替换嵌套的Either 是一个更好的主意,可能看看flatMap 这个。

标签: java-8 functional-programming either vavr


【解决方案1】:

您可能想要使用flatMap 而不是mapflatMap 的优点是您不会得到嵌套的任何一个,然后您需要以某种方式 unwrap (就像您当前在当前代码中使用 .right().get() 所做的那样)。

所以代码看起来像这样:

Either<Tuple2<Enum<ReportByTeamExecutionErrors>,String>, List<MayurDAO>> payloadPreparationResult =
new ReportByTeamCriteriaSchemaChecker("./json/schema/REQ_ReportByTeam_Schema.json")
    .validateSchema(payLoad)
    .flatMap(JsonPOJOBidirectionalConverter::pojofyCriteriaAllFieldsTeam)
    .flatMap(e -> {
        CriteriaTeamAllFieldsValidator validator =  new CriteriaTeamAllFieldsValidator(e);
        return (validator.validate());
    })
    .flatMap(this::retrieveRecordsAsPerCriteria)

【讨论】:

  • 是的,flatMap 可以工作 - 非常感谢 - 但听起来不是很违反直觉吗?好吧,来自 Javadoc:flatMap 返回 'this as Either if this is a Left,否则返回右映射结果',而 map 返回 'a mapped单子'!这可能解释了它,因为 map 再次“包装”了它!我不知道这是否是正确的行为。
  • 使用map,如果它是正确的(成功),您将转换该值。但是map 操作不能以Left 表示失败。这就是flatMap 的用武之地。如果您希望转换操作使用Either 指示成功失败,您应该使用flatMap。这将确保您将得到一个 flat Either 返回(而不是嵌套的 `Either)。因此名称 flatMap.
  • 同意。我知道我结束了我之前的评论,相当混乱。道歉。 map() 返回一个 Monad,但我正在寻找一个明确的投影(左或右)。因此,我可以做的是在映射器中使用模式匹配并返回显式的左或右。当然,在这种情况下,我可能会在对待“左派”时重复自己! flatMap() 将我从这一切中拯救出来,因为直到最后我对 Either 的 LeftProjection 包含的内容不感兴趣。感谢您花时间详细阐述您的观点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 2014-01-13
  • 2012-06-06
  • 2018-01-20
  • 2019-03-26
  • 1970-01-01
相关资源
最近更新 更多