2024 James B. Wilson
Colorado State University
Where to start?
What to make first?
Any "real-world" problem?
How to reuse what exists?
Can I publish a paper?
Is it "real-world" experience?
Is it math?
Can I teach it to a student?
Will my advisor understand?
Where's a proof?
How to finish it?
Will a math system take it?
Programming Idioms: logic written in simulate human language
\[\forall x.(1\leq x\leq 5\Rightarrow ...)\]
Public Domain, original copyright (c) James S. Davis
for x in [1..5] ...
Programming "Idioma" Language
Collection of idioms that can
model a symbolic logic.
Prop. (Division Algorithm).
For every \(n\in \mathbb{N}, m\in \mathbb{N}^+\) there exists \(q\in \mathbb{N},r\in \mathbb{N}_{<m}\) where \[n=qm+r.\]
Proof.
def div(n:Nat,m:PosNat): (Nat,Fin m) =
if n < m then
(0,n)
else
(1,0) + div(n-m,m)
By Gleb.svechnikov - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=58344593
William Howard
(no photo)
Haskell Curry
*So long as you phrase contradictions in the negative.
\(div:\mathbb{N}\times\mathbb{N}_{>0}\to \mathbb{N}\times \mathbb{N}_{<m}\)
Can be more precise:
\[\begin{aligned} div&:\mathbb{N}\times\mathbb{N}_{>0}\to \\ & \bigcup_{q\in \mathbb{N}}\bigcup_{r\in \mathbb{N}_{<m}} n=qm+r\end{aligned}\]
where \(n=qm+r\) is the type of data that proves equality (e.g. same place in memory; equal arithmetic circuits, etc.).
Prop. (Division Algorithm).
For every \(n\in \mathbb{N}, m\in \mathbb{N}^+\) there exists \(q\in \mathbb{N},r\in \mathbb{N}_{<m}\) where \[n=qm+r.\]
Proof.
def div(n:Nat,m:PosNat): (Nat,Fin m) =
if n < m then
(0,n)
else
(1,0) + div(n-m,m)
By Gleb.svechnikov - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=58344593
William Howard
(no photo)
Haskell Curry
*So long as you phrase contradictions in the negative.
\(div:\mathbb{N}\times\mathbb{N}_{>0}\to \mathbb{N}\times \mathbb{N}_{<m}\)
Can be more precise:
\[\begin{aligned} div&:\mathbb{N}\times\mathbb{N}_{>0}\to \\ & \bigcup_{q\in \mathbb{N}}\bigcup_{r\in \mathbb{N}_{<m}} n=qm+r\end{aligned}\]
where \(n=qm+r\) is the type of data that proves equality (e.g. same place in memory; equal arithmetic circuits, etc.).
Types are annotations to data that imply the data be used strictly by fixed rules.
E.g. Annotations
\[5\in \mathbb{Z}\qquad 5:\mathbb{Z}\qquad 5^{\mathbb{N}}\]
int x
x:Int
x // x is an integer.
Types are just documentation!
Some Prog. Lang. read these docs to double-check "type-check"; others assume the best and wait for a problem.
'5':Char, 2:Int means '5'+2 is an error;
5:Int, 2:Int allows 5+2.
--- Borrow from context
import K:Comm, I:Type from Gamma
--- Make a new type
data Vec K I where ...
Free Module : FORMATION
\[\frac{K:Comm\qquad I:Set}{K^I:Type}\quad(F_{vec})\]
// Borrow from context
import K:Comm, I:Type from Gamma
// Make a new type
class Vec[K,I] { ... }
Procedural
Functional
\(K^I\)
\(I\)
\(\Gamma\vdash K,I\)
import K:Comm, I:Type from Gamma
data Vec K I where
Unit : {K:Comm} -> {I:Type} -> (i:I) -> (Unit K I)
> Unit Float (Fin 3) 2
Unit 2 : Unit Float (Fin 3)
Free Module : INTRODUCTION
\[\frac{i:I}{e_i:K^I}\quad(I_{e-vec})\]
import K:Comm, I:Type from Gamma
class Vec[K,I]
case class Unit[K,I](i:I) extends Vec[K,I]
// e_2 in R^3
> e2 = new Unit[Float,range(3)](2)
Procedural
Functional
\(K^I\)
\(I\)
\(e\)
\(\Gamma\vdash K,I\)
import K:Comm, I:Type from Gamma
data Vec K I where
Unit : {K:Comm} -> {I:Type} -> (i:I) -> (Vec K I)
Sum : (u:Vec K I) -> (v:Vec K I) -> (Vec K I)
Scl : (a:K) -> (u:Vec K I) -> (Vec K I)
Free Module : IMPLICIT INTRODUCTIONS
\[\frac{a:K\qquad u:K^I}{a*u:K^I}\quad(I_{*-vec})\]
import K:Comm, I:Type from Gamma
class Vec[K,I]
case class Unit[K,I](i:I) extends Vec[K,I]
case class Sum[K,I](u:Vec[K,I],v:Vec[K,I]) extends Vec[K,I]
case class Scl[K,I](a:K, u:Vec[K,I]) extends Vec[K,I]
Procedural
Functional
\[\frac{u,v:K^I}{u+v:K^I}\quad(I_{+-vec})\]
Multiple intros called "Inductive Type"
import K:Comm, I:Type from Gamma
data Vec K I where
Unit : (i:I) -> (Vec K I)
Sum : (u:Vec K I) -> (v:Vec K I) -> (Vec K I)
Scl : (a:K) -> (u:Vec K I) -> (Vec K I)
--- The Universal Mapping Property
umap:{U:Mod}->(Vec K I)->(f:I->U)->U
Free Module : ELIMINATION
import K:Comm, I:Type from Gamma
class Vec[K,I] {
// Universal Mapping Property
abstract def umap[U<:Mod[K]](f:I->U):U
}
case class Unit(i:I) extends Vec[K,I]
case class Sum(u:Vec[K,I],v:Vec[K,I]) extends Vec[K,I]
case class Scl(a:K, u:Vec[K,I]) extends Vec[K,I]
Procedural
Functional
\[\frac{v:K^I\quad U:{_K Mod}\quad f:I\to U}{\hat{f}(v):U}\quad(E_{vec})\]
\(K^I\)
\(I\)
\(e\)
\(U\)
\(\exists!\hat{f}\)
\(f\)
\(\Gamma\vdash K,I\)
import K:Comm, I:Type from Gamma
data Vec K I where
Unit : (i:I) -> (Vec K I)
Sum : (u:Vec K I) -> (v:Vec K I) -> (Vec K I)
Scl : (a:K) -> (u:Vec K I) -> (Vec K I)
umap:(U:Mod)->(Vec K I)->(f:I->U)->U
---Implement the computation
umap U (Unit i) f = f i
Free Module : COMPUTATION
import K:Comm, I:Type from Gamma
class Vec[K,I] {
abstract def umap[U<:Mod[K]](f:I->U):U
}
case class Unit(i:I) extends Vec[K,I] {
// Implement the computation
override def umap(f:I->U):U = f(i)
}
case class Sum(u:Vec[K,I],v:Vec[K,I]) extends Vec[K,I]
case class Scl(a:K, u:Vec[K,I]) extends Vec[K,I]
Procedural
Functional
\[\frac{i:I\quad U:{_K Mod}\quad f:I\to U}{\hat{f}(e_i)=f(i)}\quad(C_{e-vec})\]
\(K^I\)
\(I\)
\(e\)
\(U\)
\(\exists!\hat{f}\)
\(f\)
\(\Gamma\vdash K,I\)
import K:Comm, I:Type from Gamma
data Vec K I where
Unit : (i:I) -> (Vec K I)
Sum : (u:Vec K I) -> (v:Vec K I) -> (Vec K I)
Scl : (a:K) -> (u:Vec K I) -> (Vec K I)
--- The Universal Mapping Property
umap:(U:Mod)->(Vec K I)->(f:I->U)->U
umap U (Unit i) f = f i
umap U (Sum x y) f = (umap U x f)+(umap U y f)
umap U (Scl a x) f = a*(umap U x f)
Free Module : IMPLICIT COMPUTATION
import K:Comm, I:Type from Gamma
class Vec[K,I] {
abstract def umap[U<:Mod[K]](f:I->U):U
}
case class Unit(i:I) extends Vec[K,I] {
override def umap(f:I->U):U = f(i)
}
case class Sum(u:Vec[K,I],v:Vec[K,I]) extends Vec[K,I] {
override def umap(f:I->U):U = u.umap(f)+v.umap(f)
}
case class Scl(a:K, u:Vec[K,I]) extends Vec[K,I]{
override def umap(f:I->U):U = a*u.umap(f)
}
Procedural
Functional
\[\frac{u,v:K^I\quad U:{_K Mod}\quad f:I\to U}{\hat{f}(u+v)=f(u)+f(v)}\quad(C_{+-vec})\]
\[\frac{a:K\quad v:K^I\quad U:{_K Mod}\quad f:I\to U}{\hat{f}(a*v)=a*f(v)}\quad(C_{*-vec})\]
// [ 3.14159, 2.71828]
v = Sum( Scl(3.14159, Unit(1)), Scl(2.71828, Unit(2))
Bulky syntax, but that can be fixed with a function; let that go.
HEAP
type:"Scl099F" a0001: 0000 0003, 0000 374F v0001: 7F66 A008
type:"Tree07A2"
l0001: 7F66 9800
r0001: 7F66 A000
type:"class" name:"Vec001B" K2B01:"Float64" I0458:"FinAA03" meth1:"eval" +p1:"func"<X,Y> +p2:K2B01 -r:<Y>
type:"Vec001B"
K2B01:"Float64"
I0458:"FinAA03"
type:"class"
name:"Unit70E0"
sup:"Vect001B"
type:"Vec001B"
K2B01:"Float64"
I0458:"FinAA03"
type:"class"
name:"FinAA03"
I0001:0000 0003
....
type:"Unit07A2"
i0001: 0000 0001
type:"Unit07A2"
i0001: 0000 0002
type:"Scl099F" a0001: 0000 0002, 0001 1894 v0001: 7F66 A001
type:"foo9056"
...
type:"foo9056"
...
type:"foo9056"
...
type:"bazEE01"
...
type:"Tree07A2"
l0001: 7F66 9805
r0001: 7F66 A001
type:"Tree07A2"
l0001: 7F66 9801
r0001: 7F66 98A2
....
// [ 3.14159, 2.71828]
v = Sum( Scl(3.14159, Unit(1)), Scl(2.71828, Unit(2))
HEAP
type:"Tree07A2"
l0001: 7F66 9800
r0001: 7F66 A000
type:"class" name:"Vec001B" K2B01:"Float64" I0458:"FinAA03" meth1:"eval" +p1:"func"<X,Y> +p2:K2B01 -r:<Y>
type:"Vec001B"
K2B01:"Float64"
I0458:"FinAA03"
type:"class"
name:"Unit70E0"
sup:"Vect001B"
type:"Vec001B"
K2B01:"Float64"
I0458:"FinAA03"
type:"class"
name:"FinAA03"
I0001:0000 0003
....
type:"vev009E"
a0001: 0000 0003, 0000 374F a0001: 0000 0002, 0001 1894
type:"foo9056"
...
type:"foo9056"
...
type:"foo9056"
...
type:"bazEE01"
...
type:"Tree07A2"
l0001: 7F66 9805
r0001: 7F66 A001
....
Prop. Any two free modules on \(I\) are naturally isomorphic.
Proof. Let \(\langle F_k, e^{(k)}:I\to F_k\rangle\) be free.
Then \(e^{(2)}:I\to F_2\) induces a linear map \(\hat{e}_2:F_1\to F_2\) and vice-versa \(\hat{e}^{(1)}:F_2\to F_1\). Furthermore \(\hat{e}_1\circ \hat{e}_2\circ e^{(1)}=e^{(1)}\). But so does the identity, so by uniqueness of UMP, \[\hat{e}_1\circ \hat{e}_2=id_{F_1}.\] Likewise if we reverse the composition. So these functions are isomorphisms.
Prop. Any two free modules on \(I\) are naturally isomorphic.
Proof. Let \(\langle F_k, e^{(k)}:I\to F_k\rangle\) be free.
Then \(e^{(2)}:I\to F_2\) induces a linear map \(\hat{e}_2:F_1\to F_2\) and vice-versa \(\hat{e}^{(1)}:F_2\to F_1\). Furthermore \(\hat{e}_1\circ \hat{e}_2\circ e^{(1)}=e^{(1)}\). But so does the identity, so by uniqueness of UMP, \[\hat{e}_1\circ \hat{e}_2=id_{F_1}.\] Likewise if we reverse the composition. So these functions are isomorphisms.
PROOFS CARRY ALGORITHMIC CONTENT
(Curry-Howard Isomorphism Theorem)
> my_u:MyVec[K,I] = ...
> f:I->YourVec[K,I] = i -> YourUnit[K,I](i)
> your_u = my_u.ump(f)
Prop. Any two free modules on \(I\) are naturally isomorphic.
Proof. Let \(\langle F_k, e^{(k)}:I\to F_k\rangle\) be free.
Then \(e^{(2)}:I\to F_2\) induces a linear map \(\hat{e}_2:F_1\to F_2\) and vice-versa \(\hat{e}^{(1)}:F_2\to F_1\). Furthermore \(\hat{e}_1\circ \hat{e}_2\circ e^{(1)}=e^{(1)}\). But so does the identity, so by uniqueness of UMP, \[\hat{e}_1\circ \hat{e}_2=id_{F_1}.\] Likewise if we reverse the composition. So these functions are isomorphisms.