简体   繁体   中英

How can I access type members from a trait in Scala

I'm trying to create a type that captures the idea of a pair of related types.

I'd then like to write functions parameterized over the captured types. Unfortunately, I'm unable to correctly express the types and end up with a type mismatch.

I have a strong preference for using type parameters and getting rid of the type members but I'm not sure how else to refer to the type parameters.

Here's my test code

class Types {

  trait TypePair[A, B] {
    type FROM = A
    type TO   = B
  }

  class Execute[TP <: TypePair[_, _]](func: TP#FROM => TP#TO) {

    def execute(in: TP#FROM): TP#TO = func(in)

  }

}

Here's the error message

Error:(12, 44) type mismatch;
 found   : in.type (with underlying type _$1)
 required: _$1
    def execute(in: TP#FROM): TP#TO = func(in)`

This should be enough for your first requirement.

object Types {
  sealed trait Request

  object Request {
    final case object ARequest extends Request
    final case object BRequest extends Request
  }

  sealed trait Response

  object Response {
    final case object AResponse extends Response
    final case object BResponse extends Response
  }

  trait TypePair[I <: Request, O <: Response]

  object TypePair {
    implicit final val ARequestAResponse: TypePair[Request.ARequest, Response.AResponse] =
      new TypePair[Request.ARequest, Response.AResponse]

    implicit final val BRequestAResponse: TypePair[Request.BRequest, Response.AResponse] =
      new TypePair[Request.BRequest, Response.AResponse]

    implicit final val BRequestBResponse: TypePair[Request.BRequest, Response.BResponse] =
      new TypePair[Request.BRequest, Response.BResponse]
  }

  final class Execute[-I, +O](func: I => O)(implicit ev: TypePair[I, O])  {
    def execute(in: I): O = func(in)
  }
}

I do not quite understand your second requirement, so I am not sure if this is enough for what you need. If not, feel free to leave your feedback and edit your question with more ifnormation. Or open a new one if you feel the problem is pretty different.

I think you can work around this problem if you get rid of type wildcards, for example:

class Types {

  trait TypePair[A, B] {
    type FROM = A
    type TO = B
  }

  sealed trait ABType
  case class ABTypeInt() extends ABType
  case class ABTypeString() extends ABType

  class Execute[TP <: TypePair[ABType, ABType]](func: TP#FROM => TP#TO) {

    def execute(in: TP#FROM): TP#TO = func(in)
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM