Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Lecture Notes on Parametric Polymorphism in Types and Programming Languages, Study notes of Calculus

These lecture notes from the 15-814: Types and Programming Languages course at Carnegie Mellon University, taught by Frank Pfenning, cover the topic of parametric polymorphism. Parametric polymorphism is a form of polymorphism where a function behaves the same at all possible types. The notes discuss the concept of parametric polymorphism, its benefits, and how it can be implemented in the type system.

Typology: Study notes

2021/2022

Uploaded on 09/27/2022

christopher1
christopher1 🇬🇧

4.5

(4)

222 documents

1 / 9

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Lecture Notes on
Parametric Polymorphism
15-814: Types and Programming Languages
Frank Pfenning
Lecture 11
October 9, 2018
1 Introduction
Polymorphism refers to the possibility of an expression to have multiple types.
In that sense, all the languages we have discussed so far are polymorphic.
For example, we have
λx. x :ττ
for any type
τ
. More specifically, then, we are interested in reflecting this
property in a type itself. For example, the judgment
λx. x :α. α α
expresses all the types above, but now in a single form. This means we can
now reason within the type system about polymorphic functions rather than
having to reason only at the metalevel with statements such as for all types
τ,. . .”.
Christopher Strachey [
Str00
] distinguished two forms of polymorphism:
ad hoc polymorphism and parametric polymorphism. Ad hoc polymorphism
refers to multiple types possessed by a given expression or function which
has different implementations for different types. For example,
plus
might
have type
int int int
but als
float float float
with different implemen-
tations at these two types. Similarly, a function
show :α. α string
might
convert an argument of any type into a string, but the conversion function
itself will of course have to depend on the type of the argument: printing
Booleans, integers, floating point numbers, pairs, etc. are all very different
LECT URE NO TES OC TOB ER 9, 2018
pf3
pf4
pf5
pf8
pf9

Partial preview of the text

Download Lecture Notes on Parametric Polymorphism in Types and Programming Languages and more Study notes Calculus in PDF only on Docsity!

Lecture Notes on

Parametric Polymorphism

15-814: Types and Programming Languages

Frank Pfenning

Lecture 11

October 9, 2018

1 Introduction

Polymorphism refers to the possibility of an expression to have multiple types. In that sense, all the languages we have discussed so far are polymorphic. For example, we have λx. x : τ → τ

for any type τ. More specifically, then, we are interested in reflecting this property in a type itself. For example, the judgment

λx. x : ∀α. α → α

expresses all the types above, but now in a single form. This means we can now reason within the type system about polymorphic functions rather than having to reason only at the metalevel with statements such as “for all types τ ,.. .”. Christopher Strachey [ Str00 ] distinguished two forms of polymorphism: ad hoc polymorphism and parametric polymorphism. Ad hoc polymorphism refers to multiple types possessed by a given expression or function which has different implementations for different types. For example, plus might have type int → int → int but als float → float → float with different implemen- tations at these two types. Similarly, a function show : ∀α. α → string might convert an argument of any type into a string, but the conversion function itself will of course have to depend on the type of the argument: printing Booleans, integers, floating point numbers, pairs, etc. are all very different

L11.2 Parametric Polymorphism

operations. Even though it is an important concept in programming lan- guages, in this lecture we will not be concerned with ad hoc polymorphism. In contrast, parametric polymorphism refers to a function that behaves the same at all possible types. The identity function, for example, is paramet- rically polymorphic because it just returns its argument, regardless of its type. The essence of “parametricity” wasn’t rigorously captured the beau- tiful analysis by John Reynolds [ Rey83], which we will sketch in Lecture 12 on Parametricity. In this lecture we will present typing rules and some examples.

2 Extrinsic Polymorphic Typing

We now return to the pure simply-typed λ-calculus.

τ ::= α | τ 1 → τ 2 e ::= x | λx. e | e 1 e 2

We would like the judgment e : ∀α. τ to express that e has all types [σ/α]τ for arbitrary σ. This will close an important gap in our earlier development, where the fixed type variables seemed to be inflexible. The construct ∀α. τ binds the type variable α with scope τ. As usual, we identify types that differ only in the names of their bound type variables. Now we would like to allow the following:

bool = ∀α. α → α true : bool true = λx. λy. x false : bool false = λx. λy. y

nat = ∀α. α → (α → α) → α zero : nat zero = λz. λs. z succ : nat → nat succ : λn. λz. λs. s (n z s)

This form of typing is called extrinsic because polymorphic types describe a properties of expression, but the expressions themselves remain unchanged.

L11.4 Parametric Polymorphism

The problem here lies in the instance of ∀I in the third line. We say that λy. x has type ∀α. α → α when it manifestly does not have this type. The problem is that α appears as the type of x : α in the context, so we should be not allowed to quantify over α at this point in the deduction. One way to prohibit this is the have a side condition on the rule

Γ e : τ α not free in Γ Γ e : ∀α. τ

∀I?

This would work, but in the similar situation when we wanted to avoid confusion between expression variables, we postulated that the variable was not already declared. We adopt a similar restriction here by adding a new form of context declaring type variables.

∆ ::= α 1 type,... , αn type

Here, all the αi must be distinct. The typing judgment is then generalized to

∆ ; Γ ` e : τ

where all the free type variables in Γ and τ are declared in ∆, and (as before) all free expression variables in e are declared in Γ. We express that a type is well-formed in the judgment

∆ ` τ type

For now, this is just defined compositionally—we show only two rules by way of example. We refer to these as type formation rules.

τ 1 type ∆ τ 2 type ∆ ` τ 1 ⊗ τ 2 type

⊗F

∆, α type τ type ∆ ∀α. τ type

∀F

Now we can formulate the correct rule for introducing the universal quantifier in the type.

∆, α type ; Γ e : τ ∆ ; Γ e : ∀α. τ

∀Iα

In order to keep the context ∆, α type well-formed, we imply that α is not already declared in ∆ and therefore does not occur in Γ. In future, when we might allow types in expressions, α would not be allowed to occur there as well: it must be globally fresh. Sometimes we add the superscript on the rule to remind ourselves of the freshness condition.

Parametric Polymorphism L11.

When we instantiate the quantifer to get a more specific types we need to make sure the type we substitute is well-formed.

∆ ; Γ e : ∀α. τ ∆ σ type ∆ ; Γ ` e : [σ/α]τ

∀E

Now we can easily derive that the Booleans true and false have the expected type ∀α. α → α → α. How about the conditional? Based on the usual conditional, we might expect

if : bool → τ → τ → τ

for any type τ , where the first occurrence is the ’then’ branch, the second the ’else’ branch and the final one the result of the conditional. But we can capture this without having to resort to metalevel quantification:

if : bool → ∀β. β → β → β

But this is exactly the same as

if : bool → bool

which makes sense since we saw in the lecture on the untyped λ-calculus that if = λb. b

3 Encoding Pairs

Now that we have the rules in place, we can consider if we can type some of the other constructions of generic data types in the pure λ-calculus. Recall:

pair = λx. λy. λf. f x y fst = λp. p (λx. λy. x) snd = λp. p (λx. λy. y)

With these definitions we can easily verify

fst (pair x y) = fst (λf. f x y) 7 → (λf. f x y) (λx. λy. x) 7 → x snd (pair x y) 7 →∗^ y

Parametric Polymorphism L11.

If we try to reformulate the second premise as a function, it would be (λx. λy. e′) : τ → σ → τ ′. If we think of this version of case as a function, it would have type τ ⊗ σ → (τ → σ → τ ′) → τ ′. We can now abstract over τ ′^ to obtain τ ⊗ σ → ∀γ. (τ → σ → γ) → γ. The conjecture about the representation of pairs then arises from replacing the function type an isomorphism

τ ⊗ σ ∼= ∀γ. (τ → σ → γ) → γ

Our calculations in the previous section lend support to this, although we didn’t actually prove such an isomorphism, just that the functions pair, fst, and snd satisfy the given typing and also compute correctly. Perhaps the elimination rule for sums is subject to a similar interpreta- tion? Γ e : τ + σ Γ, x : τ e 1 : τ ′^ Γ, y : σ e 2 : τ ′ Γ case e {l · x ⇒ e 1 | r · y ⇒ e 2 } : τ ′^

+E

The second premise would have type τ → τ ′, the third σ → τ ′^ and the conclusion has type τ ′. Therefore we conjecture

τ + σ ∼= ∀γ. (τ → γ) → (σ → γ) → γ

As a preliminary study, we can define

sum τ σ = ∀γ. (τ → γ) → (σ → γ) → γ inl : τ → sum τ σ inl = λx. λl. λr. l x inr : σ → sum τ σ inr = λy. λl. λr. r y case sum : sum τ σ → ∀γ. (τ → γ) → (σ → γ) → γ case sum = λs. s

Then we verify the expected reductions

case sum (inl x) z 1 z 2 7 → (inl x) z 1 z 2 7 → (λl. λr. l x) z 1 z 2 7 →^2 z 1 x case sum (inr y) z 1 z 2 7 →∗^ z 2 y

L11.8 Parametric Polymorphism

5 Predicativity

First, we summarize the language and rules of the polymorphic λ-calculus, sometimes referred to as System F, in its extrinsic formulation.

τ ::= α | τ 1 → τ 2 | ∀α. τ e ::= x | λx. e | e 1 e 2

∆, α type ; Γ e : τ ∆ ; Γ e : ∀α. τ ∀Iα^

∆ ; Γ e : ∀α. τ ∆ σ type ∆ ; Γ ` e : [σ/α]τ

∀E

Several objections may be made to this system. A practical objection is the aforementioned undecidablity of the typing judgment. A philosophical ob- jection is that the system is impredicative, that is, the domain of quantification includes the quantifier itself. The latter can be addressed by stratifying the language of types into simple types and type schemas.

Simple types τ ::= α | τ 1 → τ 2 |... Type schemas σ ::= ∀α. σ | τ

This simple stratification allows type inference using an algorithm due to Robin Milner [Mil78], which adopts a previous algorithm by Roger Hindley for combinatory logic [Hin69]. The decomposition into simple types and type schemas is the core of the solution adopted in functional languages such as OCaml, Standard ML, Haskell and even object-oriented languages such as Java where polymorphic functions are implemented in so-called generic methods and classes. The system of type schemes can be further extended (while remaining predicative) by considering a hierarchy of universes where the quantifier ranges over types at a lower universe. Systems with dependent types such as NuPrl or Agda employ universes for the added generality and sound type-theoretic foundation.

References

[Boe85] Hans Boehm. Partial polymorphic type inference is undecidable. In Proceedings of the 26th Annual Symposium on Foundations of Computer Science (FOCS’85), pages 339–345. IEEE, October 1985.

[Gir71] Jean-Yves Girard. Une extension de l’interpretation de g odel¨ al’analyse, et son application a l’ elimination des coupures dans´