T Foo<T>(T x){ return x; }
在调用点,您可以执行以下操作:
int y = Foo<int>(3);
这些类型有时也会写成这样:
Foo :: forall T. T -> T
我听人们说过,“forall就像是类型层面上的lambda抽象”。所以Foo是一个函数,它接收一个类型(例如int),并产生一个值(例如一个类型为int -> int的函数)。许多语言都可以推断类型参数,因此您可以写
Foo(3)
而不是Foo<int>(3)
。假设我们有一个类型为
forall T. T -> T
的对象f
。我们可以通过编写f<Q>
来首先传递一个类型Q
。然后,我们得到一个类型为Q -> Q
的值。但是,某些f
是无效的。例如这个f
:f<int> = (x => x+1)
f<T> = (x => x)
所以,如果我们“调用”
f<int>
,那么我们会得到一个类型为int -> int
的值,一般地,如果我们“调用”f<Q>
,那么我们会得到一个类型为Q -> Q
的值,这很好。然而,通常认为这个f
不是forall T. T -> T
类型的有效事物,因为它根据传递给它的类型执行不同的操作。forall的想法是明确禁止这样做的。另外,如果forall是类型级别的lambda,那么exists是什么?(即存在量化)。出于这些原因,似乎forall和exists并不真正是“类型级别的lambda”。但是它们到底是什么呢?我意识到这个问题相当模糊,但有人能为我澄清一下吗?
有了类型理论的知识,有人能解释一下forall和exists具体是什么吗?并且在多大程度上可以说“forall在类型层面上就像是lambda”?A possible explanation is the following:
If we look at logic, quantifiers and lambda are two different things. An example of a quantified expression is:
forall n in Integers: P(n)
So there are two parts to forall: a set to quantify over (e.g. Integers), and a predicate (e.g. P). Forall can be viewed as a higher order function:
forall n in Integers: P(n) == forall(Integers,P)
With type:
forall :: Set<T> -> (T -> bool) -> bool
Exists has the same type. Forall is like an infinite conjunction, where S[n] is the n-th elemen to of the set S:
forall(S,P) = P(S[0]) ∧ P(S[1]) ∧ P(S[2]) ...
Exists is like an infinite disjunction:
exists(S,P) = P(S[0]) ∨ P(S[1]) ∨ P(S[2]) ...
If we do an analogy with types, we could say that the type analogue of ∧ is computing the intersection type ∩, and the type analogue of ∨ computing the union type ∪. We could then define forall and exists on types as follows:
forall(S,P) = P(S[0]) ∩ P(S[1]) ∩ P(S[2]) ... exists(S,P) = P(S[0]) ∪ P(S[1]) ∪ P(S[2]) ...
So forall is an infinite intersection, and exists is an infinite union. Their types would be:
forall, exists :: Set<T> -> (T -> Type) -> Type
For example the type of the polymorphic identity function. Here
Types
is the set of all types, and->
is the type constructor for functions and=>
is lambda abstraction:
forall(Types, t => (t -> t))
Now a thing of type
forall T:Type. T -> T
is a value, not a function from types to values. It is a value whose type is the intersection of all types T -> T where T ranges over all types. When we use such a value, we do not have to apply it to a type. Instead, we use a subtype judgement:
id :: forall T:Type. T -> T id = (x => x) id2 = id :: int -> int
This downcasts
id
to have typeint -> int
. This is valid becauseint -> int
also appears in the infinite intersection.This works out nicely I think, and it clearly explains what forall is and how it is different from lambda, but this model is incompatible with what I have seen in languages like ML, F#, C#, etc. For example in F# you do
id<int>
to get the identity function on ints, which does not make sense in this model: id is a function on values, not a function on types that returns a function on values.