来自特质内的类型的隐含证据

时间:2017-08-06 00:57:36

标签: scala

假设我们有以下内容:

object MyValue {
  case class MyBoolean(record: Boolean) extends MyValue
  case class MyDouble(record: Double) extends MyValue
}

trait MyValue

和密封特性:

object MyValueGrabber {
  trait MyBooleanGrabber[T] extends MyValueGrabber[T] {
    override def apply(record: T): Option[MyValue.MyBoolean]
  }

  trait MyDoubleGrabber[T] extends MyValueGrabber[T] {
    override def apply(record: T): Option[MyValue.MyDouble]
  }
}

sealed trait MyValueGrabber[T] {
  def apply(record: T): Option[MyValue]
}

以及MyValue类型与其关联的其他类型之间的映射:

object Mapper {
  implicit val myBooleanMapper = new Mapper[MyValueGrabber.MyBooleanGrabber[_], String] {
    override def getValue: String = "found a bool"
  }

  implicit val myDoubleMapper = new Mapper[MyValueGrabber.MyDoubleGrabber[_], Long] {
    override def getValue: Long = 100L
  }
}

trait Mapper[A, B] {
  def getValue: B
}

然后我们有:

trait HolyGrail[T] {
  def name: String
  def myValueGrabber: MyValueGrabber[T]
  def getValue[U] = ???
}

问题是我们如何隐式使用Mapper来返回正确的类型U。理想情况下,它会是这样的:

def getValue[U](implicit ev: Mapper[myValueGrabber.type, U]) = ev.getValue  // doesn't work

1 个答案:

答案 0 :(得分:0)

您应该像这样使用它:

def getValue[U](implicit ev: Mapper[MyValueGrabber[T], U]) = ev.getValue

由于方法没有.type。 (他们转换的功能有,但我认为这不是你想要的。)

根据评论中的说明,我认为你想要像Shapeless'HMap这样的东西。

您可能需要稍微调整ValueGrabber特性:

sealed trait MyValueGrabber[T, -R <: MyValue] {
  def apply(record: T): Option[R]
}

sealed trait MyValueGrabber[T] {
  type R <: MyValue
  def apply(record: T): Option[R]
}

可能后者在你的getValue中更难使用:

def getValue[U, O](implicit ev: Mapper[MyValueGrabber[T] {type R = O}, U]): U = ev.getValue

前者看起来像这样(但据我所知不是你想要的):

trait HolyGrail[T, R] {
  def name: String
  def myValueGrabber: MyValueGrabber[T, R]
  def getValue[U](implicit ev: Mapper[MyValueGrabber[T, R], U]): U = ev.getValue
}

我不知道如何做你想要的东西(具有特征的路径依赖型)而没有没有形状。