2015-07-31 12 views
14

Nie mogę użyć generycznego w metodzie unapply ekstraktora wraz z niejawnym "konwerterem" do obsługi dopasowania wzorca określonego sparametryzowanego typu?Czy "ekstraktor" Scala może używać generycznych na Unapply?

Chciałbym zrobić (Zauważ użycie [T] na linii 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) 
} 

Ale pojawia się następujący błąd kompilacji

Error: (25, 10) not found: type ExampleExtractor case ExampleExtractor[String] (x) => x ^

Działa dobrze, jeśli mam tylko jedno niejawne val w zasięgu i upuszczam wskazówkę typu (patrz poniżej), ale to pokonuje obiekt.

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

Nie sądzę, że jest to obecnie możliwe, patrz [SI-884] (https://issues.scala-lang.org/browse/SI-884). –

Odpowiedz

2

Wariant Twojego dekodera wpisany ciąg wygląda obiecująco:

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) 
} 

następnie

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" 

wydaje się produkować co prosisz. Pozostaje jeden problem: wygląda na to, że próba wygenerowania ma spowodować awarię kompilatora (przynajmniej w mojej konsoli 2.10.3 SBT Scala).

Powiązane problemy