何时在 Scala 中使用 `with` 作为边界类型参数而不是 `<:` 或 `<:<`? [英] When to use `with` for bounding type parameters instead of `<:` or `<:<` in Scala?

查看:34
本文介绍了何时在 Scala 中使用 `with` 作为边界类型参数而不是 `<:` 或 `<:<`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一个问题,建议我在通常使用<:<:<<的地方使用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] 表示 CSeq[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` 作为边界类型参数而不是 `&lt;:` 或 `&lt;:&lt;`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆