综合开发

Scala: type of generic difference and type argument

微信扫一扫,分享到朋友圈

Scala: type of generic difference and type argument

Lets assume I have instance of arbitrary one-argument generic class (I’ll use List
in demonstration but this can me any other generic).

I’d like to write generic function that can take instances ( c
) and be able to understand what generic class ( A
) and what type argument ( B
) produced the class ( C
) of that instance.

I’ve come up with something like this (body of the function is not really relevant but demonstrates that C
conforms to A[B]
):

def foo[C <: A[B], A[_], B](c: C) {
  val x: A[B] = c
}

… and it compiles if you invoke it like this:

foo[List[Int], List, Int](List.empty[Int])

… but compilation fails with error if I omit explicit type arguments and rely on inference:

foo(List.empty[Int])

The error I get is:

Error:Error:line (125)inferred kinds of the type arguments (List[Int],List[Int],Nothing) do not conform to the expected kinds of the type parameters (type C,type A,type B).
List[Int]'s type parameters do not match type A's expected parameters:
class List has one type parameter, but type A has one
  foo(List.empty[Int])
  ^
    Error:Error:line (125)type mismatch;
 found   : List[Int]
 required: C
  foo(List.empty[Int])
                ^

As you can see Scala‘s type inference cannot infer the types correctly in this case (seems like it’s guess is List[Int]
instead of List
for 2nd argument and Nothing
instead of Int
for 3rd).

I assume that type bounds for foo
I’ve come up with are not precise/correct enough, so my question is how could I implement it, so Scala could infer arguments?

Note: if it helps, the assumption that all potential generics ( A
s) inherit/conform some common ancestor can be made. For example, that A
can be any collection inherited from Seq
.

Note: the example described in this question is synthetic and is a distilled part of the bigger problem I am trying to solve.

In addition to hubertp
answer, you can fix you function by removing obsolete (in you example) type variable C
, e.g:

def foo[A[_], B](c: A[B]) {
  val x: A[B] = c
}

In this case scalac would infer A[_]
as List
and B
as Int
.

Update(according to the comment).

If you need an evidence that C
is subtype of A[B]
, then use implicit:

def foo[A[_], B, C](c: C)(implicit ev: C <:< A[B]) = {
  val x: A[B] = c
}

Then it won’t compile this:

scala> foo[List, String, List[Int]](List.empty[Int])
<console>:9: error: Cannot prove that List[Int] <:< List[String].
              foo[List, String, List[Int]](List.empty[Int])

【漏洞预警】Remote Desktop Protocol远程代码执行漏洞 (CVE-2019-1181/1182)

上一篇

面试官:能说下 SpringBoot 启动原理吗?

下一篇

你也可能喜欢

评论已经被关闭。

插入图片

热门栏目

Scala&colon; type of generic difference and type argument

长按储存图像,分享给朋友