Scala 类型参数括号
我知道 trait Foo[T]
意味着 T
是参数化类型。 但有时我可以看到trait Foo[T1,T2]
,或trait Foo[T1,T2,R]
,我找不到任何地方描述里面多种类型的含义类型括号,您能指出这种情况下的用法吗?据我推测, Foo[T1,T2] 只是意味着,它定义了两个类型参数,它不必采用 T1
并返回 T2
。
当我今天阅读 playframework 文档时,我再次发现自己对这个问题感到困惑。在文档中,它说:
BodyParser[A] 基本上是一个 Iteratee[Array[Byte],A],这意味着 它接收字节块(只要网络浏览器上传一些 data)并计算类型 A 的值作为结果。
这个解释听起来像是,类型括号内的第二个类型参数是返回类型。
我还记得 trait Function2 [-T1, -T2, +R] extends AnyRef
表示一个接受 T1
和 T2
的函数,返回一个R
。
为什么他们将返回类型放在括号中?这是否意味着括号中的最后一个参数都是返回类型?或者他们只是碰巧为返回类型定义了一个新类型 R ?
I know trait Foo[T]
means T
is a parametrized type.
But some times I can see trait Foo[T1,T2]
, or trait Foo[T1,T2,R]
, I cannot find anywhere describe the meaning of multiple types inside a type bracket, could you please point me the usages in this case? From what I speculate, Foo[T1,T2] just means, it defined two type parameters, it doesn't have to be take a T1
and return a T2
.
When I read playframework documentation today, I again found myself confused about this question. In the documentation, it says:
A BodyParser[A] is basically an Iteratee[Array[Byte],A], meaning that
it receives chunks of bytes (as long as the web browser uploads some
data) and computes a value of type A as result.
This explanation sounds like, the second the type parameter inside a type bracket is a return type.
I also remember that trait Function2 [-T1, -T2, +R] extends AnyRef
means a function that takes a T1
and T2
, return a R
.
Why do they put the return type in the bracket? Does it mean all the last parameter in a bracket is a return type? Or they just happened defined a new type R for the return type?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
类型参数的意思只不过是“我需要任何类型,但我不想知道具体类型是什么”,其中“我”是编写代码的程序员。类型参数可以像任何其他类型(例如 Int、String 或 Complex)一样使用 - 唯一的区别是在使用它们之前它们是未知的。
请参阅类型
Map[A, +B]
。当你第一次阅读本文时,你无法知道 A 和 B 的用途,因此你必须阅读文档:它解释了类型及其含义。没有什么需要知道或理解的了。它们只是两种类型。可以像
Map[Key, Value]
那样调用 Map,但在源代码内部,类型参数只有一两个字母会更好。这使得区分类型参数和具体类型变得更容易。它是指定类型参数含义的文档。如果没有文档,您必须查看来源并自行查找其含义。例如,您必须使用
Function2 [-T1, -T2, +R]
来执行此操作。文档只告诉我们这一点:好的,我们知道三个类型参数中有两个是函数期望的参数,但是第三个是什么呢?我们看一下来源:
啊,现在我们知道
T1
和T2
是参数,R 是返回类型。类型参数也可以在方法签名中找到,例如map:
这就是将map 与List 一起使用时的样子。
A
可以是任何类型 - 它是列表包含的元素的类型。B
是另一种任意类型。当您知道 map 的作用时,您就知道B
的作用。否则你必须先了解地图。 map 需要一个可以将 List 的每个元素转换为另一个元素的函数。因为您知道A
代表列表的元素,您可以从自己那里派生出B
必须是A
转换为的类型。回答您所有其他问题:这不应该通过单一答案来完成。 StackOverflow 上还有很多其他问题和解答,也可以解答您的问题。
总结
当您看到例如
Foo[T1, T2]
中的某些类型参数时,您不应该开始哭泣。想一想:“好吧,我有一个 Foo,它需要 T1 和 T2,如果我想知道它们做什么,我必须阅读文档或源代码。”A type parameter means nothing more than "I need any type but I'm not interested to know what it is for a concrete type", where 'I' is the programmer who writes the code. Type parameters can used like any other types such as Int, String or Complex - the only difference is that they are not known until one uses them.
See type
Map[A, +B]
. When you first read this, you can't know what the A and B are for, thus you have to read the documentation:It explains the types and their meaning. There is nothing more to know or understand. They are just two types. It is possible to call Map something like
Map[Key, Value]
but inside of source code it is better when type parameters have only one or two letters. This makes it easier to differ between the type parameters and concrete types.It is the documentation which specifies what a type parameter means. And if there is no documentation you have to take a look to the sources and find their meaning by yourself. For example you have to do this with
Function2 [-T1, -T2, +R]
. The documentation tells us only this:Ok, we know that two of the three type parameters are parameters the function expects, but what is the third one? We take a look to the sources:
Ah, now we know that
T1
andT2
are the parameters and that R is a return type.Type parameters also can be found in method signatures like map:
This is how map looks like when you use it with a List.
A
can be any type - it is the type of the elements a list contains.B
is another arbitrary type. When you know what map does then you know whatB
does. Otherwise you have to understand map before. map expects a function which can transform each element of a List to another element. Because you know thatA
stands for the elements of the List you can derive from yourself thatB
have to be the typeA
is transformed to.To answer all your other questions: This shouldn't be done in a single answer. There are a lot of other questions and answers on StackOverflow which can also answer your questions.
Summary
When you see some type parameters for example in
Foo[T1, T2]
you should not start to cry. Think: "Ok, I have a Foo which expects a T1 and a T2 and if I want to know what they do I have to read documentation or the sources."类型括号内的多个类型意味着多个类型的类型参数化。举个例子,
这是一对值,一个具有
A
类型,另一个具有B
类型。更新:
我认为您对类型参数的语义解释过多。由多个参数参数化的类型就是这样,仅此而已。特定类型参数在类型参数列表中的位置并不使其具有任何特殊性。具体来说,类型参数列表中的最后一个参数不需要代表“返回类型”。
您引用的播放框架中的句子解释了这一特定类型的类型参数的语义。它不能推广到其他类型。对于
Function
类型也是如此:这里最后一个类型参数恰好意味着“返回类型”。但其他类型的情况不一定如此。上面的 Pair[A, B] 类型就是这样一个例子。这里B
是该对中第二个组件的类型。这里根本没有“返回类型”的概念。参数化类型的类型参数可以出现在参数化类型定义内“常规”类型可能出现的任何位置。也就是说,类型参数只是类型的名称,仅在实例化参数化类型本身时才绑定到实际类型。
考虑 Tuple 类的以下定义:
它被实例化为 Int 和 String 的元组类型,如下所示:
相同,
这本质上与官方源代码 请检查 Scala 语言规范。具体来说,第 3.4 节“基本类型和成员定义”下的 1. 第 4 个要点说:“参数化类型 C[T_1, ..., T_n] 的基本类型是类型 C 的基本类型,其中每次出现 a C 的类型参数 a_i 已替换为相应的参数类型 T_i。”
Multiple types inside a type bracket means type parametrization on multiple types. Take for example
This is a pair of values one having type
A
the other having typeB
.Update:
I think you are interpreting too much into the semantics of type parameters. A type parametrized by multiple parameters is just that and nothing more. The position of a specific type parameter in the list of type parameters does not make it special in any way. Specifically the last parameter in a list of type parameters does not need to stand for 'the return type'.
The sentence from the play framework which you quoted explains the semantics of the type parameters for this one specific type. It does not generalize to other types. The same holds for the
Function
types: here the last type parameter happens to mean 'the return type'. This is not necessarily the case for other types though. The typePair[A, B]
from above is such an example. HereB
is the type of the second component of the pair. There is no notion of a 'return type' here at all.Type parameters of a parametrized type can appear anywhere inside the definition of the parametrized type where a 'regular' type could appear. That is, type parameters are just names for types which are bound to the actual types only when the parametrized type itself is instantiated.
Consider the following definition of a class Tuple:
It is instantiated to a type of a tuple of Int and String like this:
Which is essentially the same as
For an official source check the Scala Language Specification. Specifically Section 3.4 "Base Types and Member Definitions" under 1. the 4th bullet point says: "The base types of a parameterized type C[T_1, ..., T_n] are the base types of type C , where every occurrence of a type parameter a_i of C has been replaced by the corresponding parameter type T_i."
我认为你的问题实际上可以分为三个单独的问题:
类/特征/等的多个类型参数是什么。 ?
一个典型的例子是从一种类型的对象到另一种对象的映射。如果您希望键的类型与值的类型不同,但保持两者通用,则需要两个类型参数。因此,Map[A,B] 采用泛型类型 A 的键并映射到泛型类型 B 的值。想要从书签到页面的映射的用户会将其声明为 Map[Bookmark, Page]。仅具有一种类型参数将不允许这种区别。
不,所有类型参数都是平等的公民,尽管它们对于函数对象在这个方向上具有含义。见下文。
这些 +/- 是什么?
它们限制类型参数可以绑定的内容。 Scala 示例 教程有很好的解释。请参阅第 8.2 节方差注释。
scala 中的函数是什么?
Scala 示例教程在第 8.6 节函数中对此进行了很好的解释。
I think your question can actually be broken in three separate problems:
What's with the multiple type parameters for classes/traits/etc. ?
A classic example is a map from one type of object to another. If you want the type for the keys to be different from type of the value, but keep both generic, you need two type parameters. So, a Map[A,B] takes keys of generic type A and maps to values of generic type B. A user that wants a map from Bookmarks to Pages would declare it as Map[Bookmark, Page]. Having only one type parameters would not allow this distinction.
No, all type parameters are equal citizens, though they have a meaning in that direction for function objects. See below.
What are all those +/-'s ?
They limit what the type parameters can bind to. The Scala by Example tutorial has a good explanation. See Section 8.2 Variance Annotations.
What is a function in scala?
The Scala by Example tutorial explains this well in Section 8.6 Functions.
它们的作用有点类似于类中的作用(即多类型参数),因为特征毕竟是类(没有任何构造函数),旨在作为混合添加到其他类中。
Scala 规范 给出了以下具有多个参数的 Trait 示例:
Their role is a bit similar to the ones (i.e. multiple type parameter) in a class, since traits are, after all, classes (without any constructor) meant to be added to some other class as a mixin.
The Scala spec gives the following example for Trait with multiple parameters: