Абстрагирование базовой логики ADT, использующей макросы, в трейт

Недавно я наткнулся на довольно удивительный фрагмент кода от Трэвиса Брауна @ Итерация по запечатанному в Scala?. Он превращает ADT на основе sealed trait + case class/object в нечто более близкое к истинным перечислениям, позволяя перечислять «конструкторы» ADT (в терминах Haskell). Поэтому я удалил 2 из 3 предупреждений об устаревании, которые выдавал код Трэвиса, и в итоге получил http://pastebin.com/L1gYGJWh который я затем использовал следующим образом:

sealed trait KeywordType
case object Crime extends KeywordType
case object Gambling extends KeywordType
case object Porn extends KeywordType

object KeywordType {
  /** Maps e.g. "Crime" to Crime */
  def withName(x: String): Option[KeywordType] =
    adt.enumerate[KeywordType].find(_.toString === x)
}

Однако мне быстро понадобилось повторно использовать ту же часть логики withName, поэтому я попытался написать следующий базовый трейт ADT:

trait ADT[T] {
  def all: Set[T] = enumerate[T]

  def withName(name: String): Option[T] =
    all.find(_.toString === name)
}

Однако это не компилирует предоставление:

Can only enumerate values of a sealed trait or class

Хотя я понимаю, почему возникает эта ошибка, я понятия не имею, как сказать системе типов «отложить» эту проверку до тех пор, пока что-то действительно не унаследуется от ADT.

Возможно ли это даже с текущей системой макросов в Scala 2.11.2 или мне нужно найти (частичный) обходной путь?


person Erik Kaplun    schedule 14.09.2014    source источник
comment
Как бы то ни было, я просто попытался решить эту проблему более принципиальным способом с помощью Shapeless и столкнулся с странным поведением. .   -  person Travis Brown    schedule 15.09.2014