【问题标题】:Scala Upper type bounds implicitly?Scala 上类型边界隐含?
【发布时间】:2020-07-22 16:42:50
【问题描述】:

我有一个这样的trait:

trait FirstTrait[U] {
  val myVal: U
}

还有一个如下:

trait SecondTrait[T <: firstTrait[U],U]

对于我正在做的实现:

case class FirstImpl(myVal: MyType) extends FirstTrait[MyType]

object SecondImpl extends SecondTrait[FirstImpl,MyType]

有没有更好的方法来做同样的事情,如果可能的话,我想像这样简化我对第二个特征的实现:

object SecondImpl extends SecondTrait[FirstImpl]

编辑

我在两个函数中都使用了:

  def func[T <: FirstTrait[U],U](myVal: T): U

当我使用存在类型时,我必须显式类型,否则我会收到 "inferred type arguments [FirstImpl,Nothing] do not conform to method func" 错误。

所以这就是我必须实现该功能的方式:

val myVal : MyType = MyType()
func[FirstImpl,MyType](FirstImpl(myVal))

有什么可以简化的吗?

【问题讨论】:

    标签: scala generics type-inference type-bounds


    【解决方案1】:

    你可以试试存在型

    trait FirstTrait[U] {
      type _U = U
      val myVal: U
    }
    
    trait SecondTrait[T <: FirstTrait[_]]
    
    case class FirstImpl(myVal: MyType) extends FirstTrait[MyType]
    
    object SecondImpl extends SecondTrait[FirstImpl]
    
    def func[T <: FirstTrait[_]](myVal: T): myVal._U = ???
    
    func(FirstImpl(myVal)): MyType
    

    或

    trait FirstTrait {
      type U
      val myVal: U
    }
    
    trait SecondTrait[T <: FirstTrait]
    
    case class FirstImpl(myVal: MyType) extends FirstTrait { type U = MyType }
    
    object SecondImpl extends SecondTrait[FirstImpl]
    
    def func[T <: FirstTrait](myVal: T): myVal.U = ???
    
    func(FirstImpl(myVal)): MyType
    

    或

    def func[T, U](myVal: T)(implicit ev: T <:< FirstTrait[U]): U = ???
    

    【讨论】:

    • 谢谢,我使用了存在类型,它的作品!但是我的问题转移到了其他地方。如果您有任何想法,我已经编辑了我的问题
    • @LucE 使用我的第二种方法,您可以定义def func[T &lt;: FirstTrait](myVal: T): myVal.U = ??? 然后func(FirstImpl(myVal)) 编译并具有MyType 类型。
    • @LucE 或者使用第一种方法,您可以添加类型 _U: trait FirstTrait[U] { type _U = U; val myVal: U } 并定义 def func[T &lt;: FirstTrait[_]](myVal: T): myVal._U = ???。然后再次func(FirstImpl(myVal)) 编译并具有类型MyType。
    • 谢谢,这真是个好主意。我用存在类型的答案和@alexey-romanov 的答案解决了我的问题,并在参数中提到了 U 的技巧,这更容易实现
    • @LucE 除了 AlexeyRomanov 的另一个变体是def func[T, U](myVal: T)(implicit ev: T &lt;:&lt; FirstTrait[U]): U = ???
    【解决方案2】:
    def func[T <: FirstTrait[U],U](myVal: T): U    
    

    问题是myVal 的类型没有提到U,所以编译器无法同时推断它与T。如果它首先推断出T,它可以从中得到U,但它目前不是这样工作的。

    不过T在这里其实是没用的,可以改写成

    def func[U](myVal: FirstTrait[U]): U    
    

    您已经可以在此处传递FirstTrait[U] 的任何子类型,并丢失类型推断问题的根源。

    如果这是一个简化的签名,一个可行的技巧是在参数类型中提及U,即使它应该是多余的:

    def func[T <: FirstTrait[U], U](myVal: T with FirstTrait[U]): U    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 1970-01-01
      • 2021-01-24
      • 2013-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多