Может ли Scala "экстрактор" использовать дженерики при неприменении?
Не могу ли я использовать общий метод unapply
экстрактора вместе с неявным "конвертером" для поддержки соответствия шаблона, специфичного для параметризованного типа?
Я хотел бы сделать это (Обратите внимание на использование [T]
в строке unapply
),
trait StringDecoder[A] {
def fromString(string: String): Option[A]
}
object ExampleExtractor {
def unapply[T](a: String)(implicit evidence: StringDecoder[T]): Option[T] = {
evidence.fromString(a)
}
}
object Example extends App {
implicit val stringDecoder = new StringDecoder[String] {
def fromString(string: String): Option[String] = Some(string)
}
implicit val intDecoder = new StringDecoder[Int] {
def fromString(string: String): Option[Int] = Some(string.charAt(0).toInt)
}
val result = "hello" match {
case ExampleExtractor[String](x) => x // <- type hint barfs
}
println(result)
}
Но я получаю следующую ошибку компиляции
Error: (25, 10) not found: type ExampleExtractor
case ExampleExtractor[String] (x) => x
^
Он отлично работает, если у меня есть только один неявный val
в области видимости и отбрасывать подсказку типа (см. ниже), но это побеждает объект.
object Example extends App {
implicit val intDecoder = new StringDecoder[Int] {
def fromString(string: String): Option[Int] = Some(string.charAt(0).toInt)
}
val result = "hello" match {
case ExampleExtractor(x) => x
}
println(result)
}
Ответы
Ответ 1
Вариант вашего типизированного декодера строк выглядит многообещающим:
trait StringDecoder[A] {
def fromString(s: String): Option[A]
}
class ExampleExtractor[T](ev: StringDecoder[T]) {
def unapply(s: String) = ev.fromString(s)
}
object ExampleExtractor {
def apply[A](implicit ev: StringDecoder[A]) = new ExampleExtractor(ev)
}
затем
implicit val intDecoder = new StringDecoder[Int] {
def fromString(s: String) = scala.util.Try {
Integer.parseInt(s)
}.toOption
}
val asInt = ExampleExtractor[Int]
val asInt(Nb) = "1111"
похоже, создает то, о чем вы просите. Остается одна проблема: кажется, что попытка
val ExampleExtractor[Int](nB) = "1111"
приводит к сбою компилятора (по крайней мере, внутри моей консоли 2.10.3 SBT Scala).