You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala Cats库的Validated相关代码无法编译该如何解决?

问题根因

  • 编译报错的核心原因是ValidationResult类型别名定义在了Expression特质内部,属于路径依赖类型:不同Expression实例的ValidationResult在编译器视角下是完全不同的类型,无法匹配mapN所需的Semigroupal类型类实例。
  • 额外逻辑问题:原有Division的除零校验仅匹配字面量Number(0)的场景,若右操作数是复合表达式(求值后结果为0),会漏掉校验导致运行时错误。

修复方案

将ValidationResult类型别名移到Expression特质外部,让所有校验返回值共用同一个类型,同时调整Division的校验逻辑,先求值再判断是否除零。

修复后完整代码

import cats.implicits._
import cats.data._
import cats.data.Validated._

// 类型别名移到特质外部,避免路径依赖问题
type ValidationResult[A] = ValidatedNel[String, A]

sealed trait Expression {
  def eval: ValidationResult[Double] = {
    this match {
      case Addition(left, right) =>
        (left.eval, right.eval).mapN(_ + _)
      case Number(value) => value.validNel
      case Division(left, right) =>
        // 先对左右表达式求值,再校验除零场景,覆盖复合表达式的情况
        (left.eval, right.eval).andThen { case (leftVal, rightVal) =>
          if (rightVal == 0) "Divide by zero".invalidNel
          else (leftVal / rightVal).validNel
        }
    }
  }
}

final case class Addition(left: Expression, right: Expression) extends Expression
final case class Division(left: Expression, right: Expression) extends Expression
final case class Number(value: Double) extends Expression

// 测试代码
val l = Division(Number(5), Number(0))
val r = Division(Number(10), Number(0))
println(Addition(l, r).eval)
// 输出:Invalid(NonEmptyList(Divide by zero, Divide by zero))

可选兼容方案

如果不想改动类型别名的位置,也可以在调用mapN时明确将返回值归属为ValidatedNel[String, Double]类型,打破路径依赖限制:

(left.eval: ValidatedNel[String, Double], right.eval: ValidatedNel[String, Double]).mapN(_ + _)

内容的提问来源于stack exchange,提问作者SkyOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 07:45:05