Scala的“抽取器”能在unapply上使用泛型吗?

16

我能不能在提取器的unapply方法上使用一个通用类型和一个隐式“转换器”来支持针对参数化类型的特定模式匹配呢?

我想做到这一点(请注意unapply行中使用了[T]),

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 - Peter Neyens
1个回答

3

您的字符串解码器的变体看起来很有前途:

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控制台中如此)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接