简体   繁体   English

对于泛型类型和它的类型参数的Scala类型推断 - 为什么它不起作用?

[英]Scala type inference for both a generic type and it's type parameter - why doesn't it work?

If I were to name the single most annoying thing about scala, it would be that for the following code: 如果我要说出关于scala的最令人烦恼的事情,那么对于以下代码:

trait G[+T]
class H[+T] extends G[T]

def f[A<:G[X], X<:Int](g :A)

val g :H[Int]
f(g)

the compiler infers types of the last call to f[H[Int], Nothing] and complains before me for its own stupidity. 编译器推断最后一次调用f [H [Int],Nothing]的类型,并在我面前因为自己的愚蠢而抱怨。

Knowing scala however, it actually knows better than me. 然而,知道scala,它实际上比我更清楚。 What's the reason behind it? 它背后的原因是什么? As both G and H are covariant regarding to T, S <: G[X] with H[_] <=> S<: H[X] for any type S. This one shortcoming made me design everything around avoiding having to specify the types explicitly - it may look like nothing here, but when names become of 'real' length and pretty much any method is generic, and often working on two generic types, it turns out that most of the code are type declarations. 由于G和H对于T都是协变的,对于任何类型S, S <: G[X] with H[_] <=> S<: H[X] 。这一个缺点使我设计了一切,避免必须指定明确的类型 - 它可能在这里看起来没什么,但是当名称变成'真实'长度并且几乎任何方法都是通用的,并且经常处理两种泛型类型时,事实证明大多数代码都是类型声明。

EDIT: the case above was solved below by Noah, but what when derived class is not of the same kind as the base class, as below? 编辑:上面的案例在下面由Noah解决,但是当派生类与基类不同时,如下所示?

trait G[+X]
class H[+X, Y] extends G[X]
class F extends G[Int]
def f[A<:G[X], X<:Int](g :A) = g

val h: H[Int, String] = ???
val g :F = ???
f(g)
f(h)

If you make A take a type paramater A[_] I think you can get the Scala compiler to agree with you instead of just making everything Nothing : 如果你让A坐式paramater A[_]我认为你可以得到Scala编译器同意你的观点,而不是仅仅让一切Nothing

def f[A[_] <: G[_], X <: Int](g: A[X]) 

As a side note, I usually take a look in the scalaz source whenever I have a type problem as they have usually encountered it and solved it as best as possible. 作为旁注,我通常会在我遇到类型问题时查看scalaz源代码,因为他们通常会遇到它并尽可能地解决它。

UPDATE UPDATE

The method I provided above still works with the additional constraints given: 我上面提供的方法仍然适用于给出的附加约束:

  trait G[+X]

  class H[+X, Y] extends G[X]

  class F extends G[Int]

  class I extends G[String]

  def f[A[_] <: G[_], X <: Int](g: A[X]) = g

  val h: H[Int, String] = new H[Int, String]
  val g: F = new F
  val i:I = new I
  f(g) //works
  f(h) //works
  f(i) // should fail and does fail

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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