Scala 将 _ param 解释为 Any => [Any]

Scala interprets _ param as Any => [Any]

我有一个枚举定义如下

enum Operator[T](val expr: String, val tag: T):

  case Plus(override val tag: T) extends Operator("+", tag)
  case Minus(override val tag: T) extends Operator("-", tag)
  case Multiply(override val tag: T) extends Operator("*", tag)

接下来是一个函数调用,它检查传递的运算符列表是否以某个运算符开头

def extract[A](expect: Operator[A], operators: List[Operator[A]]): Either[Error[A], (Operator[A], List[Operator[A]])] =
  operators match {
    case `expect` :: tail  => Right(expect, operators.tail)
    case _ =>
      expect match {
        case Plus(_)       => Left(Error.ExpectPlus(operators))
        case Minus(_)      => Left(Error.ExpectMinus(operators))
        case Multiply(_)   => Left(Error.ExpectMultiply(operators))
      }
  }

但是当我用下面的参数调用函数时,我得到如下错误

extract(Plus(_), operators)
^^^^^^^^^^^^^^^
[error]     |                               Found:    Any => Operator[Any]
[error]     |                               Required: Operator[Any]

谁能帮我解释一下为什么使用_作为参数会被解释为Any => [Any],有什么办法可以解决这个错误吗?

这是片段:https://scastie.scala-lang.org/XLrcrUBvSneJs60w87k43A

你写的和下面一样:

extract(x => Plus(x), operators)
// Same as:
extract(Plus(_), operators)

含义 Plus(_) 定义了一个函数,这不是 extract 所期望的。

这实际上是对@Luis Miguel Mejía Suárez 的评论和@Gaël J 的回答的补充。正如前面评论和答案中所述,您实际上是在将函数而不是 Operator 实例传递给提取函数。我认为您打算做的是对 Plus 中的标记使用通配符(当然这不是通配符,这会产生一个函数)。基于这些假设,我认为您正在寻找的是类型匹配。所以这需要一点重构,现在这段代码是用 Scala 2 编写的,但这些概念也应该非常适用于 Scala 3:

// I have defined the Operator as sealed abstract class earlier, and all the subtypes

sealed trait Err[OP <: Operator[_]]
object Err {
  def apply[T <: Operator[_]]: Err[T] = new Err[T] {} // In Scala3 you can easily do type matching here
}

import scala.reflect.ClassTag

def extract[A, OperatorType <: Operator[A] : ClassTag](operators: List[Operator[A]]): Either[Err[OperatorType], (Operator[A], List[Operator[A]])] = {
  operators match {
    case (head : OperatorType) :: tail =>
      Right(head, tail)
    case _ => Left(Err[OperatorType])
  }
}

val ops: List[Operator[Int]] = List(Plus(2), Minus(4), Multiply(7))
val shouldFail = extract[Int, Minus[Int]](ops) // fails since first element is not of type Minus
val shouldSucceed = extract[Int, Plus[Int]](ops) // succeeds

scastie