结构细化中的参数类型可能不是指抽象类型

时间:2017-05-10 12:28:40

标签: scala

以下代码不起作用:

trait A {
  type C

  val Extract: {
    def unapply(c: C): Option[Int] 
  }
}

错误如下:

  

错误:结构细化中的参数类型可能不会引用在该细化之外定义的抽象类型

我想写上面的内容,以便强制特质A的用户定义一个具有unapply方法的对象或值,以便我可以在模式匹配中使用它。
我找到了两个解决方法,感谢"Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"Scala: "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement"(见下文),但第一个是强制性的继承,如果我尝试链接到外部库,这是不可行的;而对于第二种情况,我放弃了覆盖Extract以更多方法的可能性。

变通方法

trait A {
  type C

  trait Extractable {
    def unapply(c: C): Option[Int]
  }

  val Extract: Extractable
}

trait A {
  type C

  def extract(c: C): Option[Int]

  object Extract {
    def unapply(c: C): Option[Int]  = extract(c)
  }
}

有没有办法(可能不是结构类型)我可以表达用户可以按照他想要的方式实现Extract的想法,只要它有所请求签名的方法unapply

1 个答案:

答案 0 :(得分:1)

你考虑过类型课吗? A只是声明其类型参数必须是“可提取的”,也就是说,范围中必须存在类型为Extractable[C]的隐式值(这只需要您实现unapply)。这可以来自您,来自其他一些图书馆或来自用户本人。

但这意味着,对于给定类型Extractable[C],您不能同时拥有多个C;也就是说,对于某些给定类型Extractable(例如C),Int只有一个实现。这与您的用例一致吗?

trait Extractable[C] {
  def unapply(c: C): Option[Int]
}

// user can supply his own extractable:
implicit val myExtractableInt = new Extractable[Int] {
  def unapply(c: Int): Option[Int] = Some(c)
}

// class A is parameterized by some C 
// for which Extractable[C] must exist
class A[C : Extractable] {
  val c: C = ???
  implicitly[Extractable[C]].unapply(c)
}

编辑:

要使A成为特征,我们需要一个(又一个)解决方法:

trait Extractable[C] {
  def unapply(c: C): Option[Int]
}

// class A is parameterized by C
// for which Extractable[C] must exist
trait A[C] {
  implicit def e: Extractable[C]
  val c: C = ???
  e.unapply(c)
}

class SomeClass extends A[Int] {
  // we need an implicit Extractable[Int],
  // either from some import or custom one
  implicit def e = new Extractable[Int] {
    def unapply(c: Int): Option[Int] = Some(c)
  }
}