# Foundations of the gerku language
## Abstract
We outline here the theoretical foundation that inspired the development of the `gerku` language.
In [1] a method is presented to automatically derive ๐-functions (or, equivalently, Combinatory Logic terms) from the definition of iterative functions.
The method relies on encoding data types with ๐-functions (or CL terms) in a specific way so that deriving the ๐-function (or CL term) to compute an iterative function is completely automatic.
We will only present the general idea here, using practical examples. The original papers (see bibliography) provide a more formal description.
The last section contains a full example on how to write a program that reverses a given list.
The `gerku` project objectives are:
- to prove that the same results hold in Concatenative Combinatory Logic (see [3])
- to create an interpreter to execute programs automatically derived from their iterative definition.
## Data types
We define a *data type* ๐ as a pair of sets:
```
๐ = โจ{*carriers*}, {*constructors*}โฉ
```
Let's define some common data types.
### Natural numbers (โ)
Natural numbers (โ) are defined by Peano's axioms:
- 0 is a natural number;
- if ๐ is a natural number then ๐(๐) is a natural number;
- nothing else is a natural number.
Any natural number can be represented as ๐(๐( ... ๐(๐(0)) ... )).
The *constructors* of natural numbers are the two functions 0:โ and ๐:โโญขโ.
We can say that the data type for natural numbers is:
```
๐ = โจ{โ}, {๐:โโญขโ , 0:โ}โฉ
```
### Pairs (โ)
The carrier set of a data type contains all the elements of the data type but can also contain other elements that are not generated by the constructors but are given a priori. Let's call them *atoms*.
```
๐ = โจ{๐ธ,โ}, {pair:๐ธร๐ธโญขโ}โฉ
```
The `pair()` constructor is often abbreviated using angle brackets `โจโฉ`.
### Booleans (๐น)
```
๐ = โจ{๐น}, {true:๐น , false:๐น}โฉ
```
### Lists (๐)
Lists that can be defined by axioms similar to the ones we have used for Naturals:
- nil is a list;
- if ๐ is a list and ๐ is an atom, then cons(๐,๐) is a list;
- nothing else is a list.
Any list is represented by a term like:
```
cons(๐โ, (cons(๐โ, ... cons(๐โ,nil) ... )))
```
The data type for the lists is:
```
๐ = โจ{๐ธ,๐}, {cons:๐ธโญข๐โญข๐ , nil:๐}โฉ
```
We can abbreviate a list using the following notation `[๐โ ๐โ ... ๐โ]`.
## Iterative functions
We will focus on the class of *iterative functions* which is closed under composition.
### Iterative functions on โ
A function `๐` on Naturals is said to be *iterative* if it can be defined as follows:
```
๐(0) = โโ
๐(๐(n)) = โโ(๐(n))
```
If this definition is possible, we'll have that:
```
๐(n) = โโ(โโ( ... โโ(โโ) ... )) = โโโฟ(โโ)
โฐโโโโโโ n times โโโโโโโโโฏ
```
for example:
```
๐(3) = โโ(๐(2))
= โโ(โโ(๐(1)))
= โโ(โโ(โโ(๐(0))))
= โโ(โโ(โโ(โโ))))
```
Typical examples of iterative functions are the addition and the multiplication on Naturals:
```
add(m,0) = m
add(m,๐(n)) = ๐(add(m,n))
mult(m,0) = 0
mult(m,๐(n)) = add(m,mult(m,n))
```
### Iterative functions on โ
The pair data type has only one constructor, meaning that the iterative scheme will only have one case.
Two fundamental functions are the *projectors* that extract the elements from a pair:
```
ฮ โ(โจ๐โ,๐โโฉ) = ๐โ ฮ โ(โจ๐โ,๐โโฉ) = ๐โ
```
It's easy to see that they are iterative.
### Iterative functions on ๐
A function ๐ on lists is said to be *iterative* if it can be defined as follows:
```
๐(nil) = โโ
๐(cons(a,l)) = โโ(a,๐(l))
```
If this definition is possible, for a list of length n we'll have that:
```
๐(l) = โโ(๐โ, โโ(๐โ, ... โโ(๐โ,โโ) ... ))
โฐโโโโโโโโโโโ n times โโโโโโโโโโโโโฏ
```
Some examples of iterative functions on lists:
```
len(nil) = 0
len(cons(a,l)) = succ(len(l))
head(nil) = ๐
head(cons(a,l)) = ๐ฐโ(a,head(l))
```
The auxiliary function ๐ฐโ() returns the first among its arguments.
## Primitive Recursive functions
Let's restrict our attention on Naturals. The reasoning below can be generalized to any data type.
A function ๐ on Naturals is said to be *primitive recursive* if it can be defined as follows:
```
๐(0) = ๐โ
๐(๐(n)) = ๐โ(n,๐(n))
```
The key difference with *iterative* functions is that the recursive step depends not only on `๐(n)` but also on `n` itself.
An important property (proven in [2]) is that:
> For any primitive recursive function `๐()` , there exists an iterative function `๐น()` that (using tuples) produces the same result.
In other words: `โ๐บโ,๐บโ` such that
```
๐น(0) = ๐บโ
๐น(๐(n)) = ๐บโ(๐น(n))
```
and `โnโโ ๐(n) = ๐น(n)`
This means that working with iterative functions does not restrict us in any way.
Let's show how this works with the factorial.
```
fact(0) = 1
fact(๐(n)) = mult(๐(n),fact(n))
```
We can choose the following iterative functions:
```
๐บโ = โจ0,1โฉ
๐บโ(y) = โจ๐(ฮ โ(y)), mult(๐(ฮ โ(y)), ฮ โ(y))โฉ
```
and define the function `๐น':โโญขโ`:
```
๐น'(0) = ๐บโ = โจ0,1โฉ
๐น'(๐(n)) = ๐บโ(๐น'(n)) = โจ๐(ฮ โ(๐น'(n))), mult(๐(ฮ โ(๐น'(n))), ฮ โ(๐น'(n)))โฉ
```
which follows the iterative scheme (everything depends on `๐น'(n)`, not on `n` ).
We can now define `๐น(x) = ฮ โ(๐น'(x))` which, being the composition of iterative functions, is iterative and provides the factorial of `x`.
To show how this works, let's evaluate `F'(3)` by applying three times `๐บโ` to `๐บโ`:
```
F'(0) = ๐บโ = โจ0,1โฉ
F'(1) = ๐บโ(๐บโ) = โจ๐(ฮ โ(โจ0,1โฉ)), mult(๐(ฮ โ(โจ0,1โฉ)), ฮ โ(โจ0,1โฉ)โฉ = โจ๐(0), mult(๐(0),1)โฉ = โจ1, 1โฉ
F'(2) = ๐บโ(๐บโ(๐บโ)) = โจ๐(ฮ โ(โจ1,1โฉ)), mult(๐(ฮ โ(โจ1,1โฉ)), ฮ โ(โจ1,1โฉ)โฉ = โจ๐(1), mult(๐(1),1)โฉ = โจ2, 2โฉ
F'(3) = ๐บโ(๐บโ(๐บโ(๐บโ)) = โจ๐(ฮ โ(โจ2,2โฉ)), mult(๐(ฮ โ(โจ2,2โฉ)), ฮ โ(โจ2,2โฉ)โฉ = โจ๐(2), mult(๐(2),2)โฉ = โจ3, 6โฉ
```
It's interesting to note what happens here: instead of using the *implicit* stack provided by the recursion scheme, we manage an explicit varaible (one element of the pair) to keep track of the partial results until we reach the desired outcome.
We can use the same technique to define the *predecessor* function `๐:โโญขโ` :
```
๐(0) = 0
๐(๐(n)) = n
```
which is primitive recursive (its value depends on `n`, not on `๐(n)` as it is required by the iterative scheme).
```
๐'(0) = ๐บโ = โจ0,0โฉ
๐'(๐(n)) = ๐บโ(p'(n)) = โจ๐(ฮ โ(๐'(n))),ฮ โ(๐'(n))โฉ
๐(x) = ฮ โ(๐'(x))
```
Let's calculate the predecessor of 3:
```
๐'(0) = ๐บโ = โจ0,0โฉ
๐'(1) = ๐บโ(๐บโ) = โจ๐(ฮ โ(โจ0,0โฉ)), ฮ โ(โจ0,0โฉ)โฉ = โจ1,0โฉ
๐'(2) = ๐บโ(๐บโ(๐บโ)) = โจ๐(ฮ โ(โจ1,0โฉ)), ฮ โ(โจ1,0โฉ)โฉ = โจ2,1โฉ
๐'(3) = ๐บโ(๐บโ(๐บโ(๐บโ)) = โจ๐(ฮ โ(โจ2,1โฉ)), ฮ โ(โจ2,1โฉ)โฉ = โจ3,2โฉ
๐(3) = ฮ โ(๐'(3)) = ฮ โ(โจ3,2โฉ) = 2
```
## Automatic Synthesis of data constructors
Since data are represented as functions, we need to define a method to derive the ๐-function (or CL terms) that encode those functions.
The method is summarized in proposition 5.3 in [1], we'll use it to derive the CL terms for the constructors of some data type.
The resulting encoding are similar, if not exactly the same, as those commonly known as Curch-encodings [4].
In the following, combinators are in bold, variables in italics.
### Constructors of Booleans ๐น
For Booleans proposition 5.3 gives:
```
๐ญ๐ซ๐ฎ๐ ๐ก ๐ = ๐ก
๐๐๐ฅ๐ฌ๐ ๐ก ๐ = ๐
```
### Constructors of Naturals โ
For Naturals proposition 5.3 gives:
```
๐ ๐ ๐ง = ๐ง
๐ฌ ๐ ๐ ๐ง = ๐ (๐ ๐ ๐ง)
```
### Constructors of lists ๐
For Lists proposition 5.3 gives:
```
๐๐จ๐ง๐ฌ ๐ ๐ฃ ๐ ๐ = ๐ ๐ (๐ฃ ๐ ๐)
๐ง๐ข๐ฅ ๐ ๐ = ๐
```
## Automatic Synthesis of programs
This is the main result (proven in [1]) that we want to leverage in `gerku`:
> By properly representing data types with ๐-functions (or CL terms), any iterative function can be automatically translated into a program that computes that function.
This means that writing a program is a four steps process:
- Properly define the data types
- Define an encoding for the data types constructors (determine the corresponding ๐-function or CL terms)
- Write the iterative definitions for the functions to be computed by the program
- Convert the functions to ๐-function (or CL terms)
Let's write a program that reverses a given list.
### Step 1
The first step is to properly define the data type (which we already did):
```
๐ = โจ{๐ธ,๐}, {cons:๐ธโญข๐โญข๐, nil:๐}โฉ
```
### Step 2
We have already defined the combinators for list constructors in the previous section:
```
๐๐จ๐ง๐ฌ ๐ ๐ฃ ๐ ๐ = ๐ ๐ (๐ฃ ๐ ๐)
๐ง๐ข๐ฅ ๐ ๐ = ๐
```
### Step 3
Next step is to define the iterative functions we need.
We first define a *reverse cat* function that concatenates two lists in the following way:
```
rcat([๐ ๐ ๐], [๐ ๐]) = [๐ ๐ ๐ ๐ ๐]
```
It is an iterative function:
```
rcat(q,nil) = ๐ฐโ(q)
rcat(q,cons(a,l)) = cons(a,rcat(q,l)) =
```
The auxiliary function `๐ฐโ()` returns the first among its arguments.
Now we can define `rev()` in terms of `rcat()`:
```
rev(nil) = nil
rev(cons(a,l)) = rcat(cons(a,nil),rev(l))
```
Let's check that it works:
```
rev([๐ ๐ ๐]) = rcat([๐], rev([๐ ๐]))
= rcat([๐], rcat([๐] ,rev([๐])))
= rcat([๐], rcat([๐] ,rcat([๐],rev([]))))
= rcat([๐], rcat([๐] ,rcat([๐],[])))
= rcat([๐], rcat([๐] ,[๐]))
= rcat([๐], [๐ ๐])
= [๐ ๐ ๐]
```
The function `rev()` is iterative since it is defined using only iterative functions.
### Step 4
Now we use Definition 5.5 in [1] to automatically derive our programs.
That, for lists, states that given the function:
```
๐(nil) = โโ
๐(cons(a,l)) = โโ(a,๐(l))
```
the corresponding *program* is:
```
๐ ๐ฟ = ๐ฟ ๐โ ๐โ
```
where `๐ฟ` is the encoding of the list and ๐โ, ๐โ are the *programs* corresponding to the functions `โโ`, `โโ`.
Let's first identify the terms `๐โ` and `๐โ` that correspond to the iterative definition of the function:
```
๐ซ๐๐๐ญ ๐ ๐ง๐ข๐ฅ = ๐โ ๐ = ๐ โ ๐โ = ๐ (๐ ๐ฅ = ๐ฅ)
๐ซ๐๐๐ญ ๐ (๐๐จ๐ง๐ฌ ๐ ๐ฟ) = ๐โ ๐ ๐ (๐ซ๐๐๐ญ ๐ ๐ฟ)
= ๐๐จ๐ง๐ฌ ๐ (๐ซ๐๐๐ญ ๐ ๐ฟ) โ ๐โ ๐ = ๐๐จ๐ง๐ฌ
```
From definition 5.5 it must be:
```
๐ซ๐๐๐ญ ๐ ๐ฟ = ๐ฟ (๐โ ๐) (๐โ ๐)
= ๐ฟ ๐๐จ๐ง๐ฌ ๐
```
Let's check that this is correct.
Remembering the definitions of `๐๐จ๐ง๐ฌ` and `๐ง๐ข๐ฅ` found prevously.
```
๐ซ๐๐๐ญ [๐ ๐ ๐] [๐ ๐] = [๐ ๐] ๐๐จ๐ง๐ฌ [๐ ๐ ๐]
= ๐๐จ๐ง๐ฌ ๐ [๐] ๐๐จ๐ง๐ฌ [๐ ๐ ๐]
= ๐๐จ๐ง๐ฌ ๐ ([๐] ๐๐จ๐ง๐ฌ [๐ ๐ ๐])
= ๐๐จ๐ง๐ฌ ๐ (๐๐จ๐ง๐ฌ ๐ ๐ง๐ข๐ฅ ๐๐จ๐ง๐ฌ [๐ ๐ ๐])
= ๐๐จ๐ง๐ฌ ๐ (๐๐จ๐ง๐ฌ ๐ (๐ง๐ข๐ฅ ๐๐จ๐ง๐ฌ [๐ ๐ ๐]))
= ๐๐จ๐ง๐ฌ ๐ (๐๐จ๐ง๐ฌ ๐ ([๐ ๐ ๐]))
= ๐๐จ๐ง๐ฌ ๐ (๐๐จ๐ง๐ฌ ๐ [๐ ๐ ๐])
= ๐๐จ๐ง๐ฌ ๐ ([๐ ๐ ๐ ๐])
= ๐๐จ๐ง๐ฌ ๐ [๐ ๐ ๐ ๐]
= [d ๐ ๐ ๐ ๐]
```
Let's move to `๐ซ๐๐ฏ`.
```
๐ซ๐๐ฏ ๐ง๐ข๐ฅ = ๐ง๐ข๐ฅ โ ๐โ = ๐ง๐ข๐ฅ
๐ซ๐๐ฏ (๐๐จ๐ง๐ฌ ๐ ๐ฟ) = ๐ซ๐๐๐ญ [๐] (๐ซ๐๐ฏ ๐ฟ) โ ๐โ ๐ = ๐ซ๐๐๐ญ [๐]
```
We are not there yet as we need an explicit term for `๐โ` .
For this we can use the combinators `๐` and `๐` defined as follows:
```
๐ ๐ฅ ๐ฆ ๐ง = ๐ฅ (๐ฆ ๐ง)
๐ ๐ฅ ๐ฆ ๐ง = ๐ฅ ๐ง ๐ฆ
```
and get:
```
๐โ ๐ = ๐ซ๐๐๐ญ [๐]
= ๐ซ๐๐๐ญ (๐๐จ๐ง๐ฌ ๐ ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ ๐)
= ๐ซ๐๐๐ญ ((๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐)
= ๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐
โ ๐โ = ๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)
```
We can now derive the program for `๐ซ๐๐ฏ`:
```
๐ซ๐๐ฏ ๐ฟ = ๐ฟ ๐โ ๐โ = ๐ฟ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ
```
Let's check its correctness:
```
๐ซ๐๐ฏ [๐ ๐ ๐] = [๐ ๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ
= ๐๐จ๐ง๐ฌ ๐ [๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ
= (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ ([๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐ ([๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ ((๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐) ([๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ ๐) ([๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ (๐๐จ๐ง๐ฌ ๐ ๐ง๐ข๐ฅ) ([๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ [๐] ([๐ ๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ [๐] (๐๐จ๐ง๐ฌ ๐ [๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ)
= ๐ซ๐๐๐ญ [๐] ((๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ ([๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐ ([๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ ((๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐) ([๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ ๐) ([๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ (๐๐จ๐ง๐ฌ ๐ ๐ง๐ข๐ฅ) ([๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] ([๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐๐จ๐ง๐ฌ ๐ ๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] ((๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ)) ๐ (๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ))) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐ (๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ))) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ ((๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ) ๐) (๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ))) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ ๐) (๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ))) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ (๐๐จ๐ง๐ฌ ๐ ๐ง๐ข๐ฅ) (๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ))) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ง๐ข๐ฅ (๐ ๐ซ๐๐๐ญ (๐ ๐๐จ๐ง๐ฌ ๐ง๐ข๐ฅ))) ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ง๐ข๐ฅ)))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] ๐ง๐ข๐ฅ))
= ๐ซ๐๐๐ญ [๐] (๐ซ๐๐๐ญ [๐] [๐])
= ๐ซ๐๐๐ญ [๐] [๐ ๐]
= [๐ ๐ ๐]
```
## Conclusion
We have summarized here the key aspects of the theory behind the `gerku` programming language.
It is still not proven if the same results will hold for Concatenative Combinators (and if yes, under which assumptions).
That's the objective of the entire project.
## Bibliography
[1] "*Automatic synthesis of typed ฮ-programs on term algebras*", Corrado Bรถhm, Alessandro Berarducci,
in "*Theoretical Computer Science*", Volume 39, 1985, Pages 135-154, https://doi.org/10.1016/0304-3975(85)90135-5.
[2] "*Reducing recursion to iteration by means of pairs and N-tuples*", Corrado Bรถhm, in proceedings "*Foundations of Logic and Functional Programming*", 1988, Springer Berlin Heidelberg. https://link.springer.com/chapter/10.1007%2F3-540-19129-1_3
[3] *The Theory of Concatenative Combinators*, Brent Kerby (bkerby at byu dot net). Completed June 19, 2002. Updated February 5, 2007. http://tunes.org/~iepos/joy.html
[4] *Church encoding*, https://en.wikipedia.org/wiki/Church_encoding