何时在 Scala 中使用 `with` 作为边界类型参数而不是 `<:` 或 `<:<`? [英] When to use `with` for bounding type parameters instead of `<:` or `<:<` in Scala?
问题描述
在 另一个问题,建议我在通常使用<:
或<:<<的地方使用
with
/代码>.因此,不要使用以下两种方式中的任何一种来定义函数:
In another question, I'm advised to use with
in a place where one normally uses <:
or <:<
. So instead of defining functions in either of the following two ways:
scala> def f[A,C <: Seq[A]](xs: C) = 0
f: [A, C <: scala.collection.immutable.Seq[A]](xs: C)Int
scala> f(List(1))
<console>:54: error: inferred type arguments [Nothing,List[Int]] do not conform to method f's type parameter bounds [A,C <: scala.collection.immutable.Seq[A]]
f(List(1))
^
scala> implicit def f[A,C](xs: C)(implicit ev: C <:< Seq[A]) = new { def foo = 0 }
f: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Seq[A]])java.lang.Object{def foo: Int}
scala> List(0) foo
<console>:54: error: Cannot prove that List[Int] <:< scala.collection.immutable.Seq[A].
List(0) foo
^
scala> f(List(0)) foo
res17: Int = 0
可以做到:
scala> implicit def f[A,C](xs: C with Seq[A]) = new { def foo = 0 }
f: [A, C](xs: C with scala.collection.immutable.Seq[A])java.lang.Object{def foo: Int}
scala> List(0) foo
res18: Int = 0
我的问题是:除了上述特殊情况,什么时候应该使用 with
而不是 <:
或 <:<
在类型参数上?为什么不总是改用with
?我正在寻找有关此处替代方案之间细微差别的讨论.谢谢.
My question is: besides the above particular case, when should one use with
instead of <:
or <:<
on the type parameter? Why not always use with
instead? I'm looking for a discussion of the nuances among the alternatives here. Thanks.
推荐答案
含义完全不同.C <:Seq[A]
表示 C
是 Seq[A]
的子类型,如你所知;xs: C with Seq[A]
没有对 C
施加任何限制,但意味着 xs
应该同时是一个 C
和一个 Seq[A]
.因此,您通常应该使用您真正指的那个.
The meanings are entirely different. C <: Seq[A]
means that C
is a subtype of Seq[A]
, as you know; xs: C with Seq[A]
doesn't put any bound on C
, but means that xs
should be both a C
and a Seq[A]
. Therefore you should normally use the one you actually mean.
在 def f[A,C <: Seq[A]](xs: C)
中,问题是 Scala 的编译器无法推断 A
因为它没有明确出现在参数类型中.原则上我没有看到任何理由它不能推断A
;它只是目前没有.用 Seq[A] 替换 C 的类型意味着
A
现在出现在 xs
的类型中,并允许编译器推断 A代码>.所以如果你真的是指边界,但是
A
被推断,你实际上需要写
In def f[A,C <: Seq[A]](xs: C)
the problem is that Scala's compiler can't infer A
because it doesn't appear explicitly in the type of arguments. I don't see any reason in principle it couldn't infer A
; it just doesn't currently. Replacing the type with C with Seq[A]
means A
now appears in the type of xs
and allows the compiler to infer A
. So if you really mean the bound, but A
to be inferred, you actually need to write
implicit def f[A,C <: Seq[A]](xs: C with Seq[A])
而不是你的第三个定义,这就是链接问题的答案.
instead of your third definition, and this is what the answer to the linked question does.
这篇关于何时在 Scala 中使用 `with` 作为边界类型参数而不是 `<:` 或 `<:<`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!