Сопоставление с образцом базового класса и всех производных классов в Scala - PullRequest
3 голосов
/ 25 февраля 2012

Я пытаюсь добиться чего-то вроде этого:

def a(b: Any) = {
  b match {
     case x: Seq[String] => println("x")
  }
}

// somewhere else

a(List("b"))

В результате я бы хотел видеть напечатанную букву "х", а я нет.

По сути, я хочу сравнить с типом / признаком и охватить все объекты, типы которых происходят от / реализуют такой тип / признак, с признаком Seq и заранее известным параметром типа. Однако, поскольку я новичок в скале, я довольно застрял.

Идеи

Ответы [ 2 ]

5 голосов
/ 25 февраля 2012

Вы не можете проверить параметризованные типы из-за стирания типов.Посмотрите на этот вопрос, почему будет предупреждение: Предупреждение о непроверенном аргументе типа в этом сопоставлении с шаблоном Scala?

Другой вопрос и ответы на него расскажут вам, как это обойти: Как мне обойти стирание типа на Scala?Или, почему я не могу получить параметр типа своих коллекций?

Тем не менее, ваш код работает нормально, если вы не проверяете параметры типа:

scala> List("a") match { case _: Seq[_] => 1 case _ => 2 }
res0: Int = 1
1 голос
/ 25 февраля 2012

Моя первая мысль - ты делаешь это неправильно.Вместо сопоставления с шаблоном вам нужен класс типов или какой-то другой механизм (методы класса), который может выполнять динамическую диспетчеризацию на основе типов.Использование сопоставления с образцом для выполнения собственной диспетчеризации на основе типов создает беспорядочный код и мешает безопасности типов.

Вот быстрый и распространенный пример класса типов в Scala.Во-первых, определите черту, которую имеет общий класс типов:

trait Ord[T] { def compare (x: T, y: T): Boolean }

В вашем случае вы бы хотели, чтобы метод a был методом черты.Затем для каждого типа, которому вы хотите принадлежать к классу типов, создайте для него неявный объект:

implicit object ordInt extends Ord[Int] {
  def compare (x: Int, y: Int) = x <= y
}

Здесь я сделал Int экземпляр моего класса Ord типа.Теперь вы можете писать методы, которые полагаются на интерфейс, предоставляемый вашим классом типов.Метод должен неявно принимать конкретный объект класса типа, например, так:

def sort[T](xs: List[T])(implicit ord: Ord[T]) = {

затем вы можете использовать специальные методы класса класса, вызывая его для неявного объекта.

def sort[T](xs: List[T])(implicit ord: Ord[T]) = {
  def insert(y: T, ys: List[T]): List[T] = ys match {
    case Nil => List(y)
    case z :: zs =>
      if (ord.compare(y,z)) { y::z::zs } // <--- here I use ord.compare
      else { z :: insert(y, zs) }
  }
  xs.foldRight(List[T]())(insert _)
}

И вуаля!У нас есть тип-ориентированная отправка, без потери безопасности типа.Хотите отсортировать список Ints?Нет проблем.Пытаетесь отсортировать список чего-то, у кого нет экземпляра Ord?Компилятор не позволит вам выстрелить себе в ногу.

...