何时使用`with`作为边界类型参数而不是Scala中的`<:`或`<:<`?

Yan*_*ang 5 scala

在另一个问题中,我建议with在通常使用<:或使用的地方使用<:<.因此,不是以下列两种方式之一定义函数:

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
Run Code Online (Sandbox Code Playgroud)

人们可以这样做:

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
Run Code Online (Sandbox Code Playgroud)

我的问题是:除了上述的特定情况下,一个时,应使用with,而不是<:或<:<对类型参数?为什么不总是使用with?我正在寻找关于替代方案中细微差别的讨论.谢谢.

Ale*_*nov 9

意义完全不同.如你所知,这C <: Seq[A]意味着它C是一个子类型Seq[A]; xs: C with Seq[A]没有任何限制C,但意味着xs应该是a C和a Seq[A].因此,您通常应该使用您实际意味着的那个.

在def f[A,C <: Seq[A]](xs: C)问题是,Scala的编译器无法推断A,因为它没有在参数的类型明确出现.我认为原则上没有任何理由无法推断A; 它目前没有.与更换型C with Seq[A]装置A现在出现在的类型xs和允许编译器推断A.所以,如果你真的是指束缚,但A要推断,你实际上需要写

implicit def f[A,C <: Seq[A]](xs: C with Seq[A])
Run Code Online (Sandbox Code Playgroud)

而不是你的第三个定义,这就是链接问题的答案.