当我编写像 def foo[A,B]
这样的函数时,[A,B]
到底是什么意思?我知道这是一个Polymorphic Method ;但是什么时候使用 foo [A]
和 foo [A,B]
呢?
这是一个我不明白其中区别的例子。该函数编译:
def map[B](f: A => B): Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
然而这个不能编译。我不明白为什么不需要 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))
(这是来自 FP in Scala 练习之一)
附录
阅读答案后,我添加了一些上下文,以帮助 future 的读者。该函数在特征内定义:
trait Stream[+A] {
...
def map[B](f: A => B):Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
...
}
所以错误是由类型阴影引起的,但请参阅下面 @acjay 的出色答案。
谷歌搜索 scala 类型遮蔽
不会在任何 scala 文档中产生直接定义,这很有趣,因为正如 @travisbrown 下面所说,它是“初学者困惑的最常见来源之一”我见过”。这里有一个讨论:Why does Scala support shadow variables?
最佳答案
在第一个示例中,只有一个类型参数,因为它不是一个孤立的函数,它是类 Stream[A]
中的一个方法,它声明了第一个类型参数。大概是这样的:
class Stream[A] {
// ...
def map[B](f: A => B): Stream[B] =
foldRight(empty[B])((h,t) => cons(f(h), t))
// ...
}
因此,您可以从周围的类范围中获取A
。假设您在伴生对象上创建了 map
方法。在这种情况下,伴生对象没有类型参数,因此您必须在方法上定义这两个参数:
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))
// ...
}
第二个选项的使用方式略有不同。您会说 Stream.map(myStream)(myMappingFunction)
而不是 myStream.map(myMappingFunction)
。这两个选项都完全有效,但将方法放入类中可能更惯用。
因此,为了回答您的问题,当两个或多个参数和/或返回类型需要是泛型时,您可以在方法上使用多个类型参数。您还可以为类使用两个类型参数,例如(忽略方差):
类型 Map[A, B]
- A
是键类型,B
是值类型
类型 Tuple2[A, B]
(更广为人知的名称是 (A, B)
) - A
是第一个元素的类型, B
是第二个元素的类型
Type Function1[A, B]
(更广为人知的是 A => B
) - A
是参数类型, B
是返回类型
...等等。
关于scala - def foo[A,B] 到底是什么意思?类型阴影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28658034/