Scala 泛型类型上的模式匹配

Scala 泛型类型上的模式匹配,scala,Scala,为什么我不能对节点[t]进行模式匹配 object Visitor { def inorder[T](root: Node[T]) : Unit = { root match { case End => return; case Node[T] => { if( root.left != null ) inorder( root.left ) println( root.toString ); in

为什么我不能对节点[t]进行模式匹配

object Visitor {
  def inorder[T](root: Node[T]) : Unit = {
    root match {
    case End => return;
    case Node[T] => {
      if( root.left != null )
          inorder( root.left )

      println( root.toString );
      inorder( root.right );
    }
    case _ => return;
    }
  }
}
更新

该代码是源代码的逐字复制

我得到了这个编译时错误:

BinaryTree.scala:25: '=>' expected but '[' found.
[error]         case Node[T] => {
[error]                  ^
[error] one error found
第25行指向该行

case Node[T] => {

为了在运行时为Scala中的泛型匹配具体化类型,您需要使用清单(q.v.),以编写代码的方式删除类型。

此行为称为
类型删除。使用
清单
可以进行变通。有关更多信息,请参阅。

我通过解释器运行了您的代码,我认为这与类型擦除无关。可能只是一些语法错误。试试这个:

object Visitor {
  def inorder[T](root: Node[T]): Unit = {
    root match {
    case End => return;
    case n:Node[_] => {
      if( root.left != null )
          inorder( root.left )

      println( root.toString );
      inorder( root.right );
    }
    case _ => return;
    }
  }
}
您需要指明将绑定到匹配项的变量名,如
n:Node[T]
。这会给您一个关于类型擦除的警告,您可以使用
n:Node[\u]
删除该警告。编译器可以根据
root
的类型推断
root.left
root.right
的类型,因此类型擦除在这里并不起作用

注意:我刚刚检查了规范,类型模式的语法是:

varid ':' TypePat
'_' ':' TypePat
如果您提供来自编译器的实际错误消息,以及Node和End的定义,这将有所帮助,否则我们需要推断所有这些内容


编辑:

假设您正在编译,代码中确实存在语法错误。使用
n:Node[\u]
。然后你会得到一些类型错误。以下是对我有效的方法:

import binarytree._
object Visitor {
  def inorder[T](root: Tree[T]) : Unit = {
    root match {
    case End => return;
    case n:Node[_] => {
      if( n.left != null )
          inorder( n.left )
      println( n.toString );
      inorder( n.right );
    }
    case _ => return;
    }
  }
}
在某些情况下,可以绑定类型参数。绑定此类类型参数可用于模式匹配子句主体的类型检查——由于擦除,这些绑定将被擦除,这意味着您无法在运行时区分它们(在.NET CLR中可以使用此类内容)

但是,您的代码似乎没有使用该类型-您需要查看Node、End的定义。实现所需的简单方法可能是忽略Node[T]的类型参数。下面是一个这样做的示例,使用正确的语法

请注意,如果要编写与某个类型(泛型或非泛型)匹配的模式,则其格式始终为
v:T
。另一方面,如果在case类上匹配,则该模式的形状为
C(p1…,pN)
。语言规范包含了所有细节

我们不必将类型绑定到类型变量
a
,还可以将其绑定到
,以强调我们不使用此类型

trait Tree[+T]
abstract class Node[+T] extends Tree[T] {
   def left: Tree[T]
   def right: Tree[T]
}
object End extends Tree[Nothing]

object Visitor {
  def inorder[T](root: Tree[T]) : Unit = {
    root match {
      case End => return;
      case node:Node[a] => {
        inorder( node.left ) // node.left has the type Tree[a]
        println( node.toString );
        inorder( node.right );
      }
      case _ => return;
    }
  }
}

不,问题不在于类型擦除,因为他没有尝试匹配已擦除的类型@huynhjl是对的,这可能只是语法问题;由于节点[T]是一种类型,因此必须使用“case u2;:Node[T]=>”。“case End=>”很好,因为End是一个值。重新阅读代码,我认为Alex是对的:Frank看到的问题是语法问题,但我没有足够的Frank代码来尝试它。理论上,我从来不知道可以在模式匹配中绑定
节点[a]
中的类型。