2015-07-31 8 views
14

Могу ли я использовать общий метод unapply экстрактора вместе с неявным «конвертером» для поддержки соответствия шаблона, специфичного для параметризованного типа?Может ли «экстрактор» 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) 
} 
+2

Я не думаю, что это возможно на данный момент, см. [SI-884] (https://issues.scala-lang.org/browse/SI-884). –

ответ

2

Вариант вашего типизированной строка декодер выглядит многообещающим:

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 консоли).

 Смежные вопросы

  • Нет связанных вопросов^_^