【问题标题】:How can I access type members from a trait in Scala如何从 Scala 中的特征访问类型成员
【发布时间】:2020-04-30 17:20:37
【问题描述】:

我正在尝试创建一个类型来捕捉一对相关类型的概念。

然后我想编写对捕获的类型进行参数化的函数。不幸的是,我无法正确表达类型并最终导致类型不匹配。

我非常喜欢使用类型参数并摆脱类型成员,但我不确定如何引用类型参数。

这是我的测试代码

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)

  }

}

这是错误信息

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

【问题讨论】:

  • 你究竟想在这里建模什么?用例是什么?假设这有效,我应该如何使用执行?我应该明确指定TP 类型吗?如果是这样,为什么?如果没有,那为什么会存在呢?
  • 我正在尝试对表示请求和响应消息类型的类对进行建模。这个想法是建立一个类型安全的函数库,可用于某些消息组。最终目标是在 TP 上创建类型类并使类型类的实例隐式可用。这将通过类型类implicit 的存在来定义TP。
  • OK,所以最终目标是: 1. 我作为用户指定类型对,系统将推断功能?或者 2. 作为用户指定功能并且系统验证这样的输入-输出对是有效的?
  • 后者。有两个主要目标。首先是确保生成正确的响应类型。第二个也是更重要的目标是静态检查是否只有对给定消息类型有效的转换可用。通过具有上下文边界的转换函数,我可以实现这一点。

标签: scala generics types existential-type


【解决方案1】:

这应该足以满足您的第一个要求。

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

我不太了解您的第二个要求,所以我不确定这是否足以满足您的需求。如果没有,请随时留下您的反馈并使用更多信息编辑您的问题。如果您觉得问题大不相同,或者打开一个新的。

【讨论】:

    【解决方案2】:

    如果你去掉类型通配符,我认为你可以解决这个问题,例如:

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

    【讨论】:

      猜你喜欢
      • 2011-05-14
      • 2021-01-03
      • 2011-01-30
      • 2015-12-30
      • 1970-01-01
      • 2021-04-22
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多