Сопоставление с образцом общего типа - PullRequest
3 голосов
/ 25 декабря 2010

Почему я не могу сопоставить шаблон с Node [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;
    }
  }
}

ОБНОВЛЕНИЕ :

Код является дословной копией 99 задач scala

Я получаю эту ошибку во время компиляции:

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

Линия 25 указывает на линию

case Node[T] => {

Ответы [ 4 ]

8 голосов
/ 25 декабря 2010

Вы можете привязать параметр типа в некоторых случаях.Привязка таких параметров типа может использоваться для проверки типов в теле предложения сопоставления с образцом - из-за стирания эти привязки стираются, и это означает, что вы не можете различить их во время выполнения (такие вещи возможны в .NET CLR).

Ваш код, похоже, не использует этот тип - нужно было бы увидеть определения Node, End.Самый простой способ достичь желаемого - это просто игнорировать аргумент типа Node [T].Ниже приведен пример, который делает это с правильным синтаксисом.

Обратите внимание, что если вы хотите написать шаблон, соответствующий типу (универсальный или нет), он всегда имеет форму v : T.Если, с другой стороны, вы подходите по классам прецедентов, то шаблон имеет формы 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;
    }
  }
}
7 голосов
/ 25 декабря 2010

Хорошо, я запускаю ваш код через интерпретатор и думаю, что он не имеет ничего общего с стиранием типов. Может быть просто какая-то синтаксическая ошибка. Попробуйте это:

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[_]. Компилятор может вывести тип root.left и root.right в зависимости от типа root, поэтому стирание типов здесь на самом деле не вступает в игру ...

Примечание: я только что проверил спецификацию, синтаксис для шаблона типа:

varid ':' TypePat
'_' ':' TypePat

Будет полезно, если вы предоставите фактическое сообщение об ошибке от компилятора и определите Node и End, так как в противном случае нам нужно будет вывести все эти вещи.


Edit:

Если вы компилируете http://aperiodic.net/phil/scala/s-99/tree.scala,, в вашем коде действительно есть синтаксическая ошибка. Используйте n:Node[_]. Тогда вы получите несколько ошибок типа. Вот что у меня работает:

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;
    }
  }
}
2 голосов
/ 25 декабря 2010

Это поведение называется type erasureManifests вы можете обойти это.См. этот вопрос для получения дополнительной информации.

2 голосов
/ 25 декабря 2010

Чтобы соответствовать типу reified во время выполнения для универсального в Scala, вам нужно использовать манифесты (q.v.). Как вы написали код, тип стирается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...