内部类型U​​依赖于特征def

时间:2017-08-06 19:42:15

标签: scala

我有自定义类型Value

trait Value
object Value {
  case class BooleanValue(record: Boolean) extends Value
  case class LongValue(record: Long) extends Value
}

一个知道如何获得Value的特征,称为GetsValue,给定一些输入类型T

sealed trait GetsValue[T] { def apply(record: T): Option[Value] }
object GetsValue {
  trait GetsBooleanValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.BooleanValue] }
  trait GetsLongValue[T] extends GetsValue[T] { override def apply(record: T): Option[Value.LongValue] }
}

请注意,GetsValue是密封的,因此用户只会展开GetsValue.GetsBooleanValueGetsValue.GetsLongValue

trait Extractor[T] {
  def title: String
  def getsValue: GetsValue[T]
  def relatedValue[U]: U = ???  // question below
}

我想要实现的目标如下:

如果getsValueGetsValue.GetsBooleanValue[_],则返回String,文字为“boo!” (即U的类型为String)。

如果getsValueGetsValue.GetsLongValue[_],则返回值为1.1的Double(即,U的类型为Double)。

另请注意,我不想匹配getsValue的{​​{1}}类型。无论类型T是什么,我都希望匹配。

如果有意义,我想使用类型class / implicits。 使用T不是我的选择。

1 个答案:

答案 0 :(得分:2)

也许这样的事情会起作用:

首先,修改GetsValue以添加指定返回类型的类型参数:

sealed trait GetsValue[T, V <: Value] { def apply(record: T): Option[V] }
object GetsValue {
  trait GetsBooleanValue[T] extends GetsValue[T, Value.BooleanValue] { }
  trait GetsLongValue[T] extends GetsValue[T, Value.LongValue] { }
}

然后使用特征将类型V与值U相关联:

trait RelatedValue[V <: Value, U] {
  def get: U
}

该特质的一些隐含价值:

object Extractor {
  implicit val boolRV = new RelatedValue[Value.BooleanValue, String] { def get = "boo!" }
  implicit val longRV = new RelatedValue[Value.LongValue, Double] { def get = 1.1 }
}

然后你的提取器特征可以是:

trait Extractor[T] {
  type V <: Value
  type U
  def title: String
  def getsValue: GetsValue[T, V]
  def relatedValue(implicit rv: RelatedValue[V, U]): U = rv.get
}

示例实现:

object Example extends Extractor[String] {
  type V = Value.BooleanValue
  type U = String
  def title = "Example"
  def getsValue = new GetsValue.GetsBooleanValue[String] {
    def apply(s: String) = None
  }
}

import Extractor._
println(Example.relatedValue)

打印“嘘!”