Недавно я наткнулся на довольно удивительный фрагмент кода от Трэвиса Брауна @ Итерация по запечатанному в 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 или мне нужно найти (частичный) обходной путь?