Expand description
Functional programming as propositions
Model is derived from PSQ, PSI and HOOO EP.
Introduction to Functional Programming
In computer science, functional programming is a programming paradigm where programs are constructed by applying and composing functions. For more information, see wikipedia article.
Foundational Path Semantics (PSI/PSQ/HOOO EP) is lower level than functional programming.
For example, a : T
in functional programming is a primitive notion, which can not be reduced
to something else. However, in foundational Path Semantics, a : T
might be modelled as
(a => T) ⋀ (a < T)
where <
is path semantical order.
Notice that in Rust, a : T
is built into the language itself.
The problem is that Rust does not support e.g. dependent types.
This is why foundational Path Semantics is needed,
to prove properties of higher level languages with more complex type systems than Rust.
The motivation is to use a small set of axioms, powerful enough to develop some intuition
in isolation, but also can be used as a starting point for more advanced logical frameworks.
There are many theorems that are provable in foundational Path Semantics, which are not provable in normal functional programming. Therefore, one should think about foundational Path Semantics as a more general model of mathematics.
Normal functional programming can be thought of as a “library” written in foundational Path Semantics. New operators and definitions are made using new axioms. However, these new axioms work in harmony with existing axioms.
For example, function composition g . f
is not a primitive notion that is built into
foundational Path Semantics. This operator needs to be defined and axioms introduced that
describe mathematical properties of function composition. When these new axioms are defined,
one can use them to prove theorems about function composition.
Types
A type x : T
uses Ty<X, T>
from the path_semantics module (PSI).
A function type f : X -> Y
uses Ty<F, Pow<Y, X>>
from the hooo module (HOOO EP).
A lambda/closure type f : X => Y
uses Ty<F, Imply<X, Y>>
.
Imaginary Inverse
For information about the imaginary inverse, see the fun::inv module.
Function Extensionality
For information about function extensionality, see the fun::fun_ext module.
Dependent Types
For information about dependent types, see the fun::dep module.
Category Theory Perspective
This model seen from a Category Theory perspective produces an ∞-groupoid.
- Object:
A: Prop
as generic argument is an objectA
in the ∞-groupoid - Morphism:
Ty<F, Pow<B, A>>
is a morphismF
fromA
toB
,f : A -> B
- Identity:
Id<A>
is the identity morphismid{A} : A -> A
- Composition:
Comp<G, F>
is the compositiong . f
- Inverse:
Inv<F>
is the imaginary inverseinv(f)
The imaginary inverse adds an inverse for every morphism in the category, which results in a groupoid. However, since the inverse is imaginary, the groupoid is category realizable.
Any expression constructed from these operations can be used where A: Prop
is allowed.
Therefore, morphisms and higher morphisms are also objects, hence this form an ∞-groupoid.
Qubit Truths
For information about qubit truths, see the fun::id module.
Re-exports
Modules
- Boolean algebra
- Dependent Types
- Equality helper macro.
- Equality
- Finite sets.
- Function Extensionality
- Identity function.
- Imaginary Inverse
- List.
- Closed natural numbers
- Natural numbers.
- Propositional Homotopy Type Theory
- Real numbers.
Structs
- Applied function.
- Duplicate function.
- Composition.
- Fst.
- Whether some symbol is a constant.
- Lambda.
f[g1 -> g2]
.f[g1 x g2 -> g3]
.- Parallel tuple.
- Snd.
- Substitute in expression
e[a := b]
. - Tuple.
- Cumulative type hierarchy.
Traits
- Implemented by variable propositions.
Functions
is_const(a) ⋀ is_const(b) => is_const(a ⋀ b)
.(f : x -> y -> z) ⋀ (a : x) ⋀ (b : y) => f(a)(b) : z
.(f : x => y => z) ⋀ (a : x) ⋀ (b : y) => f(a)(b) : z
.(x == y) => (f(x) == f(y))
.(f : (x -> y)) ⋀ (g : (x -> y)) ⋀ (f(a) == g(a))^(a : x) => ∃ a : x { f == g }
.(f(a) : y)^(a : x) => (f(b) : y)^(b : x)
.(f : (x -> y)) ⋀ (a : x) => (f(a) : y)
.(f(a)^a : x -> y)^true => (f : x -> y)
.is_const(f) ⋀ is_const(x) => is_const(f(x))
.(f : (x => y)) ⋀ (a : x) => (f(a) : y)
.(f(a) == b) ⋀ (a : x) ⋀ (b : y) => (\(a : x) = f(a)) : (x => y)
.(f == g) => (f(x) == g(y))
.(f(a) : y)^(a : x) => (f : (x -> y))
.(a : x) ⋀ (f(a) : y) => (f : (x => y))
.(f(a)^a : x => y)^true => (f : x -> y)
.theory(f(x))
.g(f(x)) => (g . f)(x)
.(f(a) == b) ⋀ (g(b) == c) => g(f(a)) == c
.(f(a) == b) ⋀ (g(b) == c) ⋀ (h == (g . f)) => h(a) == c
.h . (g . f) == (h . g) . f
.(f == h) => (f . g) == (h . g)
.(g == h) => (f . g) == (f . h)
.(f : a -> b) => (id{b} . f == f)
.(f : a -> b) => (f . id{a} == f)
.(g . f) ⋀ (g == h) => (h . f)
.(g . f) ⋀ (f == h) => (g . h)
.is_const(f) ⋀ is_const(g) => is_const(g . f)
.~f ⋀ ~g => ~(g . f)
.(g . f)(x) => g(f(x))
.(f : x -> y) ⋀ (g : y -> z) => (g . f) : x -> z
.(a == b) => (is_const(a) == is_const(b))
.is_const(a) ⋀ (a == b) => is_const(b)
.is_const(a) ⋀ is_const(b) => is_const((a, b))
.(a : b) ⋀ ((a == x) ⋁ (a == y))^(a : b) ⋀ c^(a == x) ⋀ c^(a == y) => c
.dup(a) = (a, a)
.is_const(dup)
.dup : a -> (a, a)
.(g . f)(x) == g(f(x))
.g2(f(inv(g1)(x))) == f[g1 -> g2](x)
.g3(f(inv(g1 x g2)(x))) == f[g1 x g2 -> g3](x)
.f[g1 x g2 -> g3] == f[(g1 x g2) -> g3]
.f[g1 x g2 -> g3][g4 x g5 -> g6] == f[(g1 x g2) -> g3][(g4 x g5) -> g6]
.is_const(comp)
.t : (a, b) => fst(t) : a
.fst((a, b)) = a
.is_const(fst)
.t : (x : a, b) => fst(t) == x
.fst : (a, b) -> a
.f : x -> y => f : x => y
.(a : x) ⋀ (b : y) => (a -> b) : (x -> y)
.(a : type(n)) ⋀ (b : type(m)) => (a -> b) : type(0)
.(type(n) -> type(m)) : type(0)
.is_const(a) ⋀ is_const(b) => is_const(a => b)
.(b : type(n)) => (a : b) : type(n)
.(c : x) => ((\(a : x) = b)(c) == b[a := c])
.(a : x) => ((\(a : x) = b)(a) == b
.(b : x) => ((\(a : x) = b)(b) == b
.(a : x) ⋀ (b : y) ⋀ (c : x) => ((\(a : x) = b)(c) : y)
.(b : x) => (\(a : x) = b)(b) : x
.(a : x) ⋀ (b == c) => (\(a : x) = b) == (\(a : x) = c)
.(c : x) => (\(a : x) = \(b : y) = a)(c) == (\(b : y[a := c]) = c)
.(a : x) ⋀ (b : y) => (\(a : x) = \(b : y) = a) : x
(x : type(n)) ⋀ (b : x) => (\(a : x) = a)(b) = b
.(a : x) ⋀ (b : x) => (\(a : x) = a)(b) : x
.(\(a : x) = a) == id{a}
.(\(a : x) = a) ~~ id{x}
.(a : x) => (\(a : x) = a) : (x => x)
.(a : x) ⋀ b => (\(a : x) = b)
.(c : x) => (\(a : x) = \(b : y) = b)(c) == (\(b : y[a := c]) = b)
.(a : x) ⋀ (b : y) => (\(a : x) = \(b : y) = b) : y
.(a : x) ⋀ (b : y) => (\(a : x) = b) : (x => y)
.f[g1 -> g2][g3 -> g4] == f[(g3 . g1) -> (g4 . g2)]
.f[g1 -> g2] == (g2 . f) . inv(g1)
.(f == h) => f[g1 -> g2] == h[g1 -> g2]
.(g1 == h) => f[g1 -> g2] == f[h -> g2]
.(g2 == h) => f[g1 -> g2] == f[g1 -> h]
.(f : a -> b) => (f[id{a} -> id{b}] == f)
for 1 argument.(f : a -> a) => id{a}[f -> id{a}] == inv(f)
.(f : a -> b) ⋀ (g1 : a -> c) ⋀ (g2 : b -> d) => f[g1 -> g2] : c -> d
.(inv(g1) ~~ h1) ⋀ (inv(g1) ~~ h2) ⋀ (g1(b1) = a1) ⋀ (g2(b2) = a2) ⋀ (f(b1, b2) = c) ⋀ (g3(c) = d) => f[g1 x g2 -> g3](a1, a2) = d
.f[g1 x g2 -> g3][g4 x g5 -> g6] == f[(g4 . g1) x (g5 . g2) -> (g6 . g3)]
.f[g1 x g2 -> g3] == (g3 . f) . (inv(g1) x inv(g2))
.(f == h) => f[g1 x g2 -> g3] == h[g1 x g2 -> g3]
.(f : (a1, a2) -> b) ⋀ (g1 : a1 -> c1) ⋀ (g2 : a2 -> c2) ⋀ (g3 : b -> d) => f[g1 x g2 -> g3] : (c1, c2) -> d
.is_const(a) ⋀ is_const(b) => is_const(a ⋁ b)
.is_const(f) ⋀ is_const(g) => is_const(f x g)
.(g1 x g2) . (f1 x f2) == ((g1 . f1) x (g2 . f2))
.(f(i0) == o0) ⋀ (g(i1) == o1) => (f x g)(i0, i1) == (o0, o1)
.(f : (x1 -> y1)) ⋀ (g : (x2 -> y2)) => (f x g) : ((x1, x2) -> (y1, y2))
.(id{a} x id{b}) == id{(a, b)}
.inv(f x g) == inv(f) x inv(g)
.is_const(par_tup)
.(f : (x1 => y1)) ⋀ (g : (x2 => y2)) => (f x g) : ((x1, x2) => (y1, y2))
.is_const(a) ⋀ is_const(b) => is_const(pord(a, b))
.(f : A -> B) ⋀ (inv(f) ~~ g) => ((f ~~ g) : ((A -> B) ~~ (B -> A)))
.t : (a, b) => snd(t) : a
.snd((a, b)) = b
.is_const(snd)
.t : (a, x : b) => snd(t) == x
.snd : (a, b) -> b
.f(a)[b := c] == f[b := c](a[b := c])
.is_const(a) => (a[b := c] == a)
.a[c := d] == b => a[c := d][e := f] == b[e := f]
.a[c := d] == b => (\(e) = a[c := d]) == (\(e) = b)
.(\(a : x) = b)[a := c] == b[a := c]
.(\(a : x) = b)[a := c] == b[a := c]
.a[b := b] == a
.a[a := b] == b
(a, b)[c := d] == (a[c := d], b[c := d])
.(a : b) => (b[c := a] == b)
.f[g1][g2] == f[g2 . g1]
for 1 argument.(f : a -> a) => (f[id{a}] == f)
for 1 argument.(f : a -> a) ⋀ (g : a -> b) => f[g] : b -> b
.(inv(g) ~~ h) ⋀ (g(b1) = a1) ⋀ (g(b2) = a2) ⋀ (f(b1, b2) = c) ⋀ (g(c) = d) => f[g](a1, a2) = d
.f[g1][g2] == f[g2 . g1]
for 2 arguments.(f : (a, a) -> a) => f[id{a}] == f
for 2 arguments.(f : (a, a) -> a) ⋀ (g : a -> b) => f[g] : (b, b) -> b
.(f : x => y)^true => (f^true : x -> y)
.(a == b) => (a, c, d) == (b, c, d)
.(a == b) => (c, a, d) == (c, b, d)
.(a == b) => (c, d, a) == (c, d, b)
.(a, b, c) : (x, y, z) => (a : x)
.(c : x) ⋀ (d : y) ⋀ ((a, c, d) == (b, c, d)) => (a == b)
.(c : x) ⋀ (d : y) ⋀ ((c, a, d) == (c, b, d)) => (a == b)
.(c : x) ⋀ (d : y) ⋀ ((c, d, a) == (c, d, b)) => (a == b)
.(a, b, c) : (x, y, z) => (b : y)
.(a, b, c) : (x, y, z) => (c : z)
.is_const((a, b)) => is_const(a) ⋀ is_const(b)
.(a == b) ⋀ (c == d) => (a, c) == (b, d)
.(a == b) => (a, c) == (b, c)
.(a, b) == (fst((a, b)), snd((a, b)))
.(a == b) => (c, a) == (c, b)
.(a, b) : (x, y) => (a : x)
.is_const((a, b)) => is_const(a)
.(a, b) ⋀ (a == c) => (c, b)
.(a, b) ⋀ (b == c) => (a, c)
.is_const(a) ⋀ is_const(b) => is_const((a, b))
.(c : d) ⋀ ((a, c) == (b, c)) => (a == b)
.(c : d) ⋀ ((c, a) == (c, b)) => (a == b)
.(a, b) : (x, y) => (b : y)
.is_const((a, b)) => is_const(b)
.(a : x) ⋀ (b : y) => (a, b) : (x, y)
.(type(n), type(m)) : type(0)
.is_const(a) ⋀ is_const(b) => is_const(a : b)
.type(n) => type(n+1)
.is_const(type(n))
.type(n) : type(n+1)
.
Type Definitions
- Apply 2 function arguments using function currying.
f . g
.- A proof that some symbol is not a constant.
\(a : x) = \(b : y) = a
.\(a : x) = a
.\(a : x) = \(b : y) = b
.- Apply parallel tuple to two functions.
- Apply parallel tuple to two inverted functions.
f[g]
of 1 argument.f[g]
of 2 arguments.- Tuple of 3 elements.