Установление известного отношения 1: 1 между типом и уникальным значением - PullRequest
1 голос
/ 01 марта 2011

Учитывая, что у меня есть своего рода перечисление, использующее запечатанные признаки и объекты case, представляющие значения, возможно ли применить механизм для получения единственного уникального значения для данного типа, не требуя неявного аргумента?

с имплицитами это будет

sealed trait Enum
sealed trait Value1 extends Enum
case object Value1 extends Value1 { implicit val me: Value1 = Value1 }
sealed trait Value2 extends Enum
case object Value2 extends Value2 { implicit val me: Value1 = Value1 }

def test[V <: Enum](implicit evidence: V): V = evidence

test[Value1]

можно ли отбросить неявный аргумент для проверки?то есть, чтобы убедиться, что V является определенным подтипом Enum (очевидно, test [Enum] должен провалиться).Гордиев узел:

object Enum {
  def unique[V <: Enum]: V = ???
}

?

1 Ответ

1 голос
/ 01 марта 2011

Похоже, что вы пытаетесь найти конкретные значения или поведение на основе типа и по какой-либо причине не хотите помещать это поведение в какой-то общий суперкласс.

Выглядит так, как будто вы пытаетесь использовать имплициты и сопутствующие объекты для достижения этого путем эмуляции некоторых характеристик статики Java. Это модель, которую вы абсолютно хотите исключить из своего ментального инструментария, она безнадежно сломана с точки зрения объектно-ориентированного программирования.

То, что вы действительно хотите, - это специальный полиморфизм, и у нас есть лучшие способы сделать это. Интересно, что он все еще использует импликации и границы контекста:

sealed trait Enum
sealed trait Value1 extends Enum
sealed trait Value2 extends Enum

case object Value1 extends Value1
case object Value2 extends Value2

sealed abstract class UniqValue[T] { def value: T }
implicit object Value1HasUniq extends UniqValue[Value1] { val value = Value1 }
implicit object Value2HasUniq extends UniqValue[Value2] { val value = Value2 }

def test[V <: Enum : UniqValue]: V = implicitly[UniqValue[V]].value

Вы также можете определить test как:

def test[V <: Enum](implicit ev: UniqValue[V]): V = ev.value

Что делает то же самое, вручную удаляя синтаксический сахар границ контекста, который компилятор сделает для вас в любом случае.

По сути, все это работает, потому что компиляция также учитывает параметры типа при разрешении имплицитов.

Если вы хотите больше узнать об этом, волшебная фраза для поиска - «классы типов»

...