[英]What is and when to use Scala's forSome keyword?
List[T] forSome {type T}
和List[T forSome {type T}]
什么List[T forSome {type T}]
? 我如何用“英语”阅读它们? 我应该如何神交 forSome
关键字? forSome
一些实际用途是forSome
? 什么是有用的实用和复杂的简单T forSome {type T}
用法?
这里有很多问题,其中大部分已经在上面评论中链接的答案中得到了相当彻底的解决,所以我会回答你更具体的第一个问题。
List[T] forSome { type T }
和List[T forSome { type T }]
之间没有真正有意义的区别,但我们可以看到以下两种类型之间的区别:
class Foo[A]
type Outer = List[Foo[T]] forSome { type T }
type Inner = List[Foo[T] forSome { type T }]
我们可以将第一个读作“ T
的foos列表,对于某些类型T
”。 整个列表中只有一个T
第二,在另一方面,可以理解为“FOOS的列表,其中每个foo是的T
一些T
”。
换句话说,如果我们有一个outer: Outer
列表outer: Outer
,我们可以说“存在一些类型T
,使得outer
是T
的foos列表”,其中对于Inner
类型的列表,我们只能说“对于列表的每个元素,存在一些T
,使得该元素是T
的foo”。 后者较弱 - 它告诉我们较少的清单。
因此,例如,如果我们有以下两个列表:
val inner: Inner = List(new Foo[Char], new Foo[Int])
val outer: Outer = List(new Foo[Char], new Foo[Int])
第一个将编译得很好 - 列表中的每个元素对于某些T
来说都是Foo[T]
。 第二个不会编译,因为没有一些T
这样列表中的每个元素都是Foo[T]
。
注意:( 更新2016-12-08 )根据Martin Odersky关于ScalaX 2016的讨论,forSome关键字很可能会与Scala 2.13或2.14一起消失。用路径依赖类型或匿名类型属性替换它( A[_]
)。 在大多数情况下这是可能的。 如果您的边缘情况不可能,请重构您的代码或放宽您的类型限制。
通常当您使用通用API时,API会保证您可以使用您提供的任何类型(最多一些给定的约束)。 因此,当您使用List[T]
,List API会保证它可以与您提供的任何类型T
使用 。
对于forSome
(所谓的存在量化类型参数),它是相反的。 API将提供一种类型(不是你),它保证你,它将使用它提供给你的这种类型。 语义是,具体对象会给你一些类型为T
东西。 同一个对象也会接受它为您提供的内容。 但没有其他对象可以使用这些T
s,没有其他对象可以为您提供T
类型的东西。
“存在量化”的概念是:存在(至少)一种类型T
(在实现中)以履行API的合同。 但我不会告诉你它是哪种类型。
forSome
可以读取类似:对于某些类型的T
的API合同成立。 但对于所有类型的T
都不一定如此。 因此,当您提供某种类型的T
(而不是在API的实现中隐藏的类型)时,编译器无法保证您获得了正确的T
所以它会抛出一个类型错误。
因此,当您在API中看到List[T] forSome {type T}
时,您可以这样阅读:API将为您提供一些未知类型T
的List
。 它很乐意接受这个列表,它将与它一起使用。 但它不会告诉你, T
是什么。 但至少你知道,列表中的所有元素都是相同的类型T
第二个有点棘手。 API再次为您提供一个List
。 它会使用某种类型的T
而不是告诉你T
是什么。 但是可以自由地为每个元素选择不同的类型。 真实世界的API会为T
建立一些约束,因此它实际上可以使用列表的元素。
当您编写API时, forSome
很有用,其中每个对象代表API的实现。 每个实现都将为您提供一些对象,并将接受这些对象。 但是你既不能混合不同实现的对象,也不能自己创建对象。 相反,您必须始终使用相应的API函数来获取可与该API一起使用的一些对象。 forSome
可以实现非常严格的封装。 您可以阅读forSome
通过以下方式:
对于某些类型,API合约折叠为true。 但你不知道它适用于哪种类型。 因此,您无法提供自己的类型,也无法创建自己的对象。 您必须使用通过使用
forSome
的API提供的那些。
这非常非正式,在某些极端情况下甚至可能是错误的。 但它应该帮助你理解这个概念。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.