(\n.n(\px.Sp(BxSB))K(KI)I)\f.(\l.SB(lf)f)\g.KI
Try it online! (Instructions: delete all the code there, copy the body n times and the footer on a single line, choose Nat, click Compile and then Run and see the Output.)
The observation that
Just realized that codes like I\f.f (a trailing lambda abstraction, which puts the next iteration inside its body) are accepted. This may change the conclusion about zero padding.
was correct, and there was indeed a solution without any padding.
The solution above has a structure of
x \f. y \g. z
and has the following property:
(\f. y \g. z) == 1 (\f. y \g. z x \f. y \g. z) == 2 (\f. y \g. z x \f. y \g. z x \f. y \g. z) == 3 ...
z was chosen to be KI so that we can ignore x and the equation to solve simply becomes
(\f. y \g. n) == succ n == SBn
which can be solved with y = \l.SB(lf)f. Then, x should be a function that takes n and outputs nth fibonacci number. This is solved using 2014MELO03's construction of iterating a pair.
Lambda calculus (Ben Lynn's Nat), 39 bytes, 1 byte footer
(\a.a(\zbxf.f(a(SB)b)a)(\f.fI(KI)))(KI)
Footer:
K
Try it online! (Instructions: delete all the code there, copy the body n times and the footer on a single line, choose Nat, click Compile and then Run and see the Output.)
How I got to this solution
First, there is no solution without any header or footer. This is because:
- any lambda term would be in the structure of
x1 x2 .. xn - one copy must evaluate to 1 =
I - but then 2 copies of the code evaluates to
x1 x2 .. xn x1 x2 .. xn = I x1 x2 .. xn = x1 x2 .. xn = I, which is true for any number of copies, and 1 is clearly not fib(i) for larger i (number of copies).
This logic is false due to the subtlety of the grammar of Nat. See the no-padding solution at the top.
Given this, I aimed to find a solution with a single combinator as the footer. I chose K because it fits particularly well here; specifically, if repetitions of x1 x2 .. xn evaluate to a pair, applying K on it extracts the first element. Then to simplify the problem, I assumed that n = 2, i.e. the repeating part is f x for some f and x. It can be an answer if it satisfies the following: ((x, y) refers to the Church pair of x and y.)
f x evaluates to (1, 0). (a, b) f x = f a b x evaluates to (a+b, a).
Given that a in the second case is always a Church natural number ≥ 1, I decided to set x to zero (= KI). Then I can use a simple discriminator that returns u for 0 and v for 1 or greater:
0 (\z. v) u = u a (\z. v) u = v -- when a >= 1
If the first argument is 0, we need to return (1, 0), so u = \f. f I (KI). Otherwise we take two more arguments b and x, ignore x, and construct a new pair \f. f (a succ b) a. This completes the construction of the answer above.
About choosing the interpreter and the LC language: I initially wanted to compile this to SKI calculus, but I didn't have a good one, and the three copies of a in a single lambda would surely make a mess. So I reached out for a regular LC interpreter instead, and found Nat. After getting some syntax errors (I was trying to use s for a function name), I realized that it does support SKIBC combinators out of the box, so I went with it.
(a,b)=>aoutputted 1,(a,b)=>a(a,b)=>aoutputted 2, etc. would that be okay? Or should it be a full program \$\endgroup\$