aboutsummaryrefslogtreecommitdiff
path: root/microposts/dependent-types.org
blob: 5c4d70adc185bc775a0b3066c6f494ce2a32332f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#+title: Curry-Howard correspondence and Dependent types
#+date: <2022-01-20>

What is Curry-Howard correspondence?

Roughly speaking, it says there is a one-one correspondence between
world of propositions (proofs) and world of types (programs).

A simple illustration:

For any two propositions P and Q, the proposition that P implying Q,
i.e. P -> Q, corresponds to: for any two types T and S, the functional
type T -> S.

Finding a proof of P -> Q corresponds to finding an element in T -> S.

In a more simplified setting, proving a proposition P corresponds to
finding an element of T.

In coq, one can write:

#+begin_src coq
Theorem p_implies_q : P -> Q.
#+end_src

Which looks exactly the same as, except the keywords =Theorem= and
=Definition=,

#+begin_src coq
Definition some_function : T -> S.
#+end_src

To show the pun is genuine, if you want, you can prove a definition
and define a theorem:

#+begin_src coq
Definition add_one : nat -> nat.
Proof.
  intro n.                      (* introduce the argument of the function to the context and call it n. *)
  apply succ.                   (* apply succ to the "goal" *)
  apply n.
Defined.

Definition imp_refl : forall P : Prop, P -> P := fun P p : P => p.
#+end_src

It may still feel rather forced, as the proof of the definition is way
less readable than a direct definition, and the definition of the
theorem is just plain silly (Logical Foundations has a more reasonable
example - the evenness of a number).

How about an actual example, where one cannot do without the
correspondence?  Well, look no further than dependent types!

Say you want to work with vectors, which are lists of a certain
length, which is encoded as a pair (the list, the length) with a
condition:

#+begin_src coq
Definition vector (X : Type) :=
  { '(xs, n) : list X * nat | length xs = n }.
#+end_src

This is called a dependent sum type, or sigma type, where the vertical
bar =|= serves the same role as in set theory, meaning "such that".

The full definition is a bit more involved which we will skip.

Now, how do you define a concat function that takes two vectors of
length m and n and returns a concatenated vector of length m + n?  You
will have to do two things in such a definition:

- *Define* the resulting pair.
- *Prove* the length of the resulting list is m + n.

Now there's no escaping the pun!

To learn more about this, check out [[https://softwarefoundations.cis.upenn.edu/lf-current/index.html][Logical Foundations]] and [[https://softwarefoundations.cis.upenn.edu/vfa-current/index.html][Verified
Functional Algorithms]].  More specifically, [[https://softwarefoundations.cis.upenn.edu/lf-current/ProofObjects.html][ProofObjects: The
Curry-Howard Correspondence]] and [[https://softwarefoundations.cis.upenn.edu/vfa-current/ADT.html#lab168][ADT: Abstract Data Types]].