module Realisability.PCA where
Partial combinatory algebras🔗
A partial combinatory algebra (PCA) is a set equipped with enough structure to model universal computation: a partial application operator1 and a notion of abstraction elimination, which will be defined below. This structure is enough for to model a simple programming language in the spirit of the untyped lambda calculus.
While the definition of PCA is austere, adapting traditional encoding techniques from untyped lambda calculus lets us show that PCAs support encoding booleans, pairs, sums, and even primitive recursion.
Formalising the partial application operator is slightly tricky. In the literature (e.g. following de Jong (2024)) one would imagine that the application operator on has type
_ = 𝔸 → 𝔸 → ↯ 𝔸
i.e., that it takes two defined elements of and returns a partial element. However, working with an operator of this type is rather cumbersome, because we can’t form iterated expressions like the application lives in not and so can not be the left operand in an application. Instead, we define application to work over partial elements, i.e. the type of our application operators is
PAS : Type ℓ
PAS = ↯ 𝔸 → ↯ 𝔸 → ↯ 𝔸
The inhabitants of a PCA🔗
If is a partial combinatory algebra (or, more generally, a partial applicative structure), the inhabitants of the type often serve dual purposes: they can be values or they can be programs. Of course, since PCAs implement a simple higher-order programming language, programs are a type of value. However, there are still situations where it is important to be clear which of these two roles a given is serving.
Applying a program to a given value may not result in a value— execution could diverge, for example. We think of an arbitrary application like as a computation, which may or may not produce a value— if it does produce a value, then it comes from exactly one value in
If is a partial combinatory algebra, we refer to the type as the type of values in , or programs in , depending on the role that each inhabitant is playing.
We also refer to the type as the type of computations in .
Abstraction elimination🔗
The type of terms over with free variables is defined inductively: A term is either one of the variables, a value drawn from or the application of a term to another.
data Term (A : Type ℓ) (n : Nat) : Type (level-of A) where var : Fin n → Term A n const : ↯⁺ A → Term A n app : Term A n → Term A n → Term A n
If we are given a term in
variables and an environment, a list of
values, we can define the eval
uation of a term to be the
computation obtained by looking each variable up in the environment,
preserving embedded values, and using the partial applicative structure
to interpret the app
constructor. Moreover,
if we have a term
in
variables and a term
in
variables, we can inst
antiate
with
to obtain a term in
variables, where the zeroth variable used in
has been replaced with
throughout.
module eval (_%_ : PAS A) where eval : Term A n → Vec (↯⁺ A) n → ↯ A eval (var x) ρ = lookup ρ x .fst eval (const x) ρ = x .fst eval (app f x) ρ = eval f ρ % eval x ρ inst : Term A (suc n) → Term A n → Term A n inst (var x) a with fin-view x ... | zero = a ... | suc i = var i inst (const a) _ = const a inst (app f x) a = app (inst f a) (inst x a)
These two operations are connected by the following lemma: evaluating a term instantiated with a value is the same as evaluating the original term in an extended environment.
abstract eval-inst : (t : Term A (suc n)) (x : ↯⁺ A) (ρ : Vec (↯⁺ A) n) → eval (inst t (const x)) ρ ≡ eval t (x ∷ ρ) eval-inst (var i) y ρ with fin-view i ... | zero = refl ... | suc j = refl eval-inst (const a) y ρ = refl eval-inst (app f x) y ρ = ap₂ _%_ (eval-inst f y ρ) (eval-inst x y ρ)
A partial applicative structure is a partial combinatory algebra when
we have an operation abs
sending terms
in
variables to terms
in
variables which behave, under evaluation, as “functions of
”.
In particular, functions should always be defined values (abs↓
), and we have a
restricted
law (abs-β
)
saying that applying a function to a value should be the same as
evaluating the body of the function instantiated with that value, or
equivalently in an environment extended with that value.
record is-pca (_%_ : PAS A) : Type (level-of A) where open eval _%_ public field abs : Term A (suc n) → Term A n abs↓ : (t : Term A (suc n)) (ρ : Vec (↯⁺ A) n) → ⌞ eval (abs t) ρ ⌟ abs-β : (t : Term A (suc n)) (ρ : Vec (↯⁺ A) n) (a : ↯⁺ A) → eval (abs t) ρ % a .fst ≡ eval (inst t (const a)) ρ
Traditional texts on realisability (e.g. de Jong op. cit., see also Bauer (2022)) define partial combinatory algebras in terms of combinators, typically and These can be defined using the abstraction operator in the typical way, e.g.
We prefer taking the abstraction elimination procedure as a primitive since it works better with Agda’s type inference, in particular when working against an arbitrary PCA— but a combinatorially complete partial applicative structure is a PCA in our sense.
In the formalisation we often define and apply functions to many arguments, so we define an version of the abstraction combinator and of the law.
absₙ : (k : Nat) → Term A (k + n) → Term A n absₙ zero e = e absₙ (suc k) e = absₙ k (abs e) _%ₙ_ : ∀ {n} → ↯ A → Vec (↯⁺ A) n → ↯ A a %ₙ [] = a a %ₙ (b ∷ bs) = (a %ₙ bs) % b .fst abstract abs-βₙ : {k n : Nat} {e : Term A (k + n)} → (ρ : Vec (↯⁺ A) n) (as : Vec (↯⁺ A) k) → (eval (absₙ k e) ρ %ₙ as) ≡ eval e (as ++ ρ) abs-βₙ ρ [] = refl abs-βₙ {e = e} ρ (x ∷ as) = ap (_% x .fst) (abs-βₙ ρ as) ∙ abs-β _ (as ++ ρ) x ∙ eval-inst e x (as ++ ρ)
record PCA-on (A : Type ℓ) : Type ℓ where infixl 25 _%_ field has-is-set : is-set A _%_ : ↯ A → ↯ A → ↯ A has-is-pca : is-pca _%_ open is-pca has-is-pca public PCA : (ℓ : Level) → Type (lsuc ℓ) PCA ℓ = Σ[ X ∈ Set ℓ ] PCA-on ∣ X ∣ module PCA {ℓ} (A : PCA ℓ) where open PCA-on (A .snd) public
References
- Bauer, Andrej. 2022. “Notes on Realizability.” Midlands Graduate School. https://github.com/andrejbauer/notes-on-realizability.
- de Jong, Tom. 2024. “Categorical Realizability.” Midlands Graduate School. https://github.com/tomdjong/MGS-categorical-realizability.