Implicit proofs from type within a tag

Let's say we have the following:

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

trait MyValue

      

and the sealed sign:

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

      

and also a mapping between a type MyValue

and another type with which it is associated:

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
}

      

and then we have:

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

      

The question is, how do we implicitly use Mapper

to return the correct type U

. Ideally, it would be something like:

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

      

0


source to share


1 answer


You should use it like this:

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

      

How methods don't have .type

. (Their converted function is there, but I think this is not what you want.)

Based on the clarifications in the comments, I think you want something like Shapeless' HMap .

You may have to change your trait a little ValueGrabber

:

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

      

or



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

      

perhaps the latter is harder to use in your getValue

:

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

      

the first one would look like this (but not what you want as I understand it):

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
}

      

I dont know how to do what you want (path dependent type with trait) without formless.

0


source







All Articles