[英]What exactly does def foo[A,B] mean? Type shadowing
When I write a function like def foo[A,B]
, what exactly does the [A,B]
mean? 当我写这样一个函数
def foo[A,B]
不正是[A,B]
是什么意思? I know it's a Polymorphic Method ; 我知道这是一种多态方法 ; but when do you use
foo [A]
versus foo [A,B]
? 但是何时使用
foo [A]
和foo [A,B]
?
Here's an example where I don't understand the difference. 这是一个我不了解其中差异的示例。 This function compiles:
该函数编译:
def map[B](f: A => B): Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
Whereas this one doesn't compile. 而这个不编译。 I don't understand why the
A
isn't required, after all A
is referenced by the f: A => B
: 我不明白为什么
A
不是必需的,毕竟A
被引用的f: A => B
:
def map[A,B](f: A => B): Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
[error] ..../Stream.scala:61: type mismatch;
[error] found : h.type (with underlying type A)
[error] required: A
[error] foldRight(empty[B])((h,t) => cons(f(h), t))
(this is from one of the FP in Scala exercises) (这是Scala练习中的FP之一 )
Addendum 附录
After reading the answers I'm adding some context, to help future readers. 阅读答案后,我会添加一些上下文,以帮助将来的读者。 The function is defined inside a trait:
该函数在特征内定义:
trait Stream[+A] {
...
def map[B](f: A => B):Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
...
}
So the error was being caused by type shadowing , but see @acjay's excellent answer below. 因此,错误是由阴影类型引起的,但请参见下面的@acjay最佳答案。
Googling scala type shadowing
doesn't result in a direct definition in any of the scala docs, which is interesting because as @travisbrown says below, it's "one of the most common sources of beginner confusion I've seen". 谷歌搜索
scala type shadowing
不会在任何scala文档中产生直接定义,这很有趣,因为正如@travisbrown在下面说的那样,它是“我见过的最常见的初学者困惑源之一”。 There is a discussion here: Why does Scala support shadow variables? 这里有一个讨论: Scala为什么支持阴影变量?
In the first example, there's only one type parameter because that's not a function in isolation, it's a method in class Stream[A]
, which declares the first type parameter. 在第一个示例中,只有一个类型参数,因为这不是孤立的函数,而是类
Stream[A]
,该方法声明了第一个类型参数。 Approximately like so: 大概是这样的:
class Stream[A] {
// ...
def map[B](f: A => B): Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
// ...
}
So you get the A
from the surrounding class scope. 因此,您可以从周围的类范围获得
A
Suppose instead that you made map
a method on the companion object instead. 假设您改为在对应对象上使
map
成为方法。 In this case, the companion object has no type parameter, so you have to define both parameters on the method: 在这种情况下,伴随对象没有类型参数,因此您必须在方法上定义两个参数:
class Stream[A] {
// ... methods, with foldRight, but no `map`
}
object Stream {
// ...
def map[A, B](stream: Stream[A])(f: A => B): Stream[B] =
stream.foldRight(empty[B])((h,t) => cons(f(h), t))
// ...
}
This second option would be used slightly differently. 第二个选项的使用会稍有不同。 You would say
Stream.map(myStream)(myMappingFunction)
instead of myStream.map(myMappingFunction)
. 您可能会说
Stream.map(myStream)(myMappingFunction)
而不是myStream.map(myMappingFunction)
。 Both options are perfectly valid, but it's probably more idiomatic to put the method in the class. 这两个选项都是完全有效的,但是将方法放在类中可能更惯用。
So, to answer your question, you use multiple type parameters on a method when two or more of the arguments and/or return type need to be generic. 因此,要回答您的问题,当两个或多个参数和/或返回类型需要通用时,可以在方法上使用多个类型参数。 You might also use two type parameters for classes as well, like (disregarding variance):
您可能还会对类使用两个类型参数,例如(忽略方差):
Type Map[A, B]
- A
is the key type and B
is the value type 类型
Map[A, B]
A
是键类型, B
是值类型
Type Tuple2[A, B]
(better known as (A, B)
) - A
is the type of the 1st element, B
is the type of the 2nd element 类型
Tuple2[A, B]
(又称(A, B)
)- A
是第一个元素的类型, B
是第二个元素的类型
Type Function1[A, B]
(better known as A => B
) - A
is the argument type, B
is the return type 类型
Function1[A, B]
(又称A => B
) A
是参数类型, B
是返回类型
...and so on. ...等等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.