Wild FJ 论文中类型变量和类型参数的区别?

Difference between type variable and type parameter in the Wild FJ paper?

在 2005 年 Wild FJ Torgersen 等人的论文中,第 2 节和第 3 节的第一段使用术语“类型参数”。然后3.1节第一句介绍了“类型变量”这个词。考虑到讨论它的上下文以及缺少关于 Google 的信息,我只能推测“类型变量”专门用于指代通配符。我敢肯定,这是导致在 Java.

中实施通配符的“开创性”论文

编辑:非常感谢 deduper 为编辑我的问题所做的辛勤工作!

方法foo(int x)中使用了以下术语:

  • 该方法有 1 个 形式参数 (int x),尽管它通常被缩短为参数,导致潜在的混淆。 int 参数类型 x 参数名称

  • x 是一个 参数变量 ,尽管它通常被缩写为 参数,导致潜在的混淆。

  • 在调用 foo(5) 中,该值称为 参数 ,尽管它是通常称为 参数值 ,缩写为 参数 ,导致潜在的混淆。当需要澄清时,它被称为实际参数

如您所见,shorthand 对单词 参数的使用 可以表示 int xx5,视上下文而定。

对于泛型类型,Foo<X extends Number>,使用类似的命名方式:

  • 类型有1个类型参数,其中extends Number类型绑定 X 类型标识符

  • X 是一个 类型变量 .

  • 当使用Foo<Integer>时,Integer部分被称为类型参数.类型参数可以是通配符。

不要混淆方法 parameter type 和泛型 type parameter

如您所见,您得出的 ""type variable" 专门用于指代通配符" 的结论是不正确的。 类型变量指的是类型参数名称,与类型参数是否绑定无关

类型变量的"actual"类型,即类型参数,可以是也可以不是通配符,因为它是在泛型类型的使用中指定的,而不是在泛型类型的定义中.

泛型类型变量仅在泛型类型的定义中被引用,类似于方法参数变量仅被引用在方法的主体中。

全文搜索显示 "type variable" 首先出现在第 2 节中:

As long as the element type is known at the call site, this may be expressed with plain generics using apolymorphic method with a dummy type variable:

〈X〉void m1(List〈X〉list) { ... }

如您所见,此示例根本不使用通配符,这与您的假设相矛盾 "type variable is used to refer to wildcards specifically".

那么,什么类型的变量?由于该术语未在论文本身中定义,因此必须在其参考文献之一中对其进行定义。

但是哪一个?由于习惯上在首次使用术语之前包含参考文献,参考文献必须在介绍部分,从上下文来看,这句话看起来最有希望:

Parametric polymorphism — also known as genericity or generics — originated in the world offunctional programming [21]

所以我们很有可能在

中找到答案

[21] Robin Milner. A theory of type polymorphism in programming. Journal of Computer and System Sciences, 17:348–375, August 1978.

通过谷歌搜索该论文的标题可以找到包含全文的 PDF,事实上,该经典论文包含大量类型变量的示例,例如:

EXAMPLE 1.

Mapping a function over a list.

let rec map(f, m) = if null (m) then nil 
                    else cons (f(hd(m)), map (f, d(m)))

Intuitively, the function map so declared takes a function from things of one sort to things of another sort, and a list of things of the first sort, and produces a list of things of the second sort. So we say that map has type

((α → β) x α list) → β list

where α, β are type variables.

因此,类型变量只是一个包含类型的变量(在数学意义上)。类型变量可以通过类型参数引入,但正如 Milner 所示,类型变量也可以通过其他方式引入。 (注意 α 和 β 如何没有出现在 map 的定义中?)

当 Java 编译器执行通配符捕获时,会发生类似的情况。例如,如果我们写:

List<?> sourceList = ...;
List<?> targetList = ...;
targetList.add(sourceList.get(0));

编译器说:

The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (capture#2-of ?)

正如我们所见,在对通配符类型进行推理时,编译器"captures"将通配符的值转化为新的类型变量,例如capture#1-of ?。与类型参数引入的类型变量不同,这些类型变量永远不会出现在源代码中。

这就是为什么在讨论通配符捕获时,Wild FJ 论文谈到了类型参数未引入的类型变量。