<p>While <a href="https://medium.com/@aems/closures-vs-curried-functions-vs-partial-application-66889658a03" rel="noreferrer">reading about currying</a>, I found the argument that it is beneficial in languages, which have only functions accepting only one argument.</p>
<p>I am wondering how to implement a 2-ary function like the addition in a language having only 1-ary functions?</p>
<p>The cited blog gives the following example:</p>
<pre class="lang-typescript prettyprint-override"><code>function threeArity(x: number, y: number, z: number): number {
    return x + y + z;
}

function curriedThree(x: number): (y: number) =&gt; ((z: number) =&gt; number) {
    return function (y: number): (z: number) =&gt; number {
        return function (z: number): number {
            return x + y + z;
        }
    }
}

console.log(threeArity(1, 2, 3));
console.log(curriedThree(1)(2)(3));
</code></pre>
<p>But I think this is cheating, because in the end the 2-ary <code>+</code> is used.  If the language has only 1-ary functions such a 2-ary <code>+</code> can not exist. How would a 1-ary addition look like?</p>

<functional-programming><currying>
How to implement + in a language where functions accept only one argument?
CC BY-SA 4.0
2023-11-24T17:56:58.283Z
You can go as deep down the rabbit hole as you like. The answers go as far as Church encoding. If you're interested in the abstract details of the bit, then there's your answer. If you're interested in doing currying in a practical programming language, then using a bootstrapped or built-in `+` is your answer.
Silvio Mayolo
CC BY-SA 4.0
2023-11-24T18:16:26.867Z
I don't understand this as a question about language design or implementation. When you implement a programming language, you generally do so in a different language (the host language). So even if your language doesn't support 2-ary functions or operators, you can still implement your curried "plus" function using the host language's `+` operator.
kaya3
CC BY-SA 4.0
2023-11-24T20:11:59.797Z
@kaya3, the point is that you can't self-express the fundamentals of the language, following your logic. Obviously, a simplistic and limited language can always be expressed by calling into a more fundamental and more complete language. A language considering only of 1-adic functions is a simplistic and limited language, which is either computationally useless, or it is implemented in terms of a much more complicated assembly language (i.e. it relies on causing certain computations to occur which cannot be expressed in the language itself).
Steve
CC BY-SA 4.0
2023-11-24T21:59:30.530Z
@Steve That's not a language design or implementation problem, though. In practice a language doesn't need to self-express its own native operations (including addition), they are implemented in some other language, or ultimately implemented by logic gates in hardware.
kaya3
CC BY-SA 4.0
2023-11-25T04:17:27.740Z
@kaya3, it's a problem for those who are trying to discern whether they've understood a particular language correctly, and whether a particular language incorporates concepts that can cope with all essential aspects of what a computer *does*. Even hardware gates have multiple inputs as standard. The purpose of questions like these is not to understand languages in their own terms - it is to establish whether a particular language is fit to be integrated into an all-encompassing mental model. So what the language claims to do has to reconcile globally within your own understanding. (1/2)
Steve
CC BY-SA 4.0
2023-11-25T04:18:42.833Z
The purpose of this reconciliation is to drive out contradiction. The OP has clearly got the impression that all computation can be modelled with only 1-adic functions. I'm as interested in that question as he is, and that claim doesn't in fact seem to be true. Like him, I can't seem to find a logic where you don't need to operate on two values at once, in order to implement addition. This simultaneous presence of two values seems irreducible, and cannot be expressed as a series of operations on just one value each turn. (2/2)
Steve
CC BY-SA 4.0
2023-11-25T16:15:18.123Z
@Steve: Formally, currying implies pairs; Cartesian-closed categories have products whenever they have exponentials. I'm not sure whether this would be an acceptable answer, but it is certainly the formal answer.
Corbin
CC BY-SA 4.0
2023-11-25T21:09:06.910Z
@Steve Questions about understanding how real languages work (e.g. Haskell or F# both only have unary functions) are better suited for Stack Overflow, or if it's about what's theoretically possible with only unary functions/lambda calculus then one of [Computer Science](https://cs.stackexchange.com/) or [CS Theory](https://cstheory.stackexchange.com/) would seem to be the appropriate venue. As I said, I don't see how this question is about language design or implementation.
kaya3
CC BY-SA 4.0
2023-11-26T12:19:29.663Z
[This question is being discussed on meta.](https://langdev.meta.stackexchange.com/q/614/89)
kaya3
CC BY-SA 4.0
2023-11-29T23:25:29.633Z
I mentioned this in one of the comment rooms, but I thought the original asker might find this helpful. I made an implementation of a language that only has single argument functions, function application and a print function. I have a web-based REPL where you can use it with your browser [here](https://roboguy13.github.io/utlc-eval/), along with a bunch of examples. I have numbers implemented as Church numerals. For example, if you try `mult two three (print a) id` it will print `a` six times. As the implementor, I can tell you there are no multi-argument functions in the language.
David Young
CC BY-SA 4.0
2023-11-29T23:27:20.213Z
It also has a REPL command that will compile an expression to Python. The Python code will be a huge monstrosity but if you look carefully you will note: Even in this compiled version, not a multi-argument function (or tuple, etc) in sight!
David Young
<p>Assuming a functional language with currying and only unary functions where <code>add</code> implements addition:</p>
<ul>
<li><code>add</code> has type <code>int -&gt; (int -&gt; int)</code></li>
<li><code>add 5</code> returns an (anonymous) unary function that adds 5 to its argument</li>
<li><code>(add 5) 7</code> would apply this function to <code>7</code> - resulting in <code>12</code>.</li>
</ul>
<p>Usually the parentheses are not written explicitly because <code>-&gt;</code> is right associative and function application is left associative.</p>
<p>Transforming <code>x + y</code> into <code>add x y</code> is purely syntactical and is performed by the parser of the language.</p>

CC BY-SA 4.0
2023-11-24T10:18:44.120Z
2023-11-24T10:18:44.120Z
Christian Lindig
CC BY-SA 4.0
2023-11-25T06:34:12.047Z
**Comments have been [moved to chat](https://chat.stackexchange.com/rooms/149900/discussion-on-answer-by-christian-lindig-how-to-implement-in-a-language-where); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.
Michael Homer
<blockquote>
<p>I think this is cheating, because in the end the 2-ary + is used.
If the language has only 1-ary functions such a 2-ary + can not exist.</p>
</blockquote>
<p>Not so—in GHC Haskell, the <a href="https://hackage.haskell.org/package/base-4.19.0.0/docs/GHC-Exts.html#g:4" rel="nofollow noreferrer">primitive operations</a> are still defined with curried function types. For instance, the unboxed integer addition operator is this: <code>(+#) :: Int# -&gt; Int# -&gt; Int#</code>. If you apply it to two operands, it can compile directly to an addition instruction; but you can also allocate a closure by applying it to only one operand.</p>
<p>In JavaScript, of course that isn’t the case: the curried function needs to be defined in terms of the binary <code>+</code> operator. However, it’s worth noting that in JavaScript and many other languages, this is a primitive binary operation that <em>isn’t</em> a function.</p>
<p>In a similar vein, Haskell’s tuple type can be constructed with a function <code>(,) :: a -&gt; b -&gt; (a, b)</code>, or with built-in tuple <em>syntax</em>, which has its own typing rule unrelated to functions: <code>(e1, e2) :: (A, B)</code> if <code>e1 :: A</code> and <code>e2 :: B</code>.</p>
<blockquote>
<p>How would a 1-ary addition look like?</p>
</blockquote>
<p>If we don’t have any primitive binary operations like addition, we might still implement it using only a unary increment operation. But supposing we didn’t even have that, we could still construct it using <a href="https://en.wikipedia.org/wiki/Church_encoding" rel="nofollow noreferrer">Church encoding</a>.</p>
<p>Numerals are made from the zero numeral <code>Z</code> and the successor function <code>S</code>. A numeral has two parameters: an “increment” function for the inductive case, and an initial “zero” value for the base case. Its numeric value is encoded implicitly, in unary, by the number of times that it applies the function to the value. For example, 2 is <code>S(S(Z))</code>.</p>
<pre class="lang-js prettyprint-override"><code>const Z =
  (inc) =&gt; (zero) =&gt; zero;

const S =
  (n_times) =&gt;
    (inc) =&gt; (zero) =&gt; inc(n_times(inc)(zero));
</code></pre>
<p>The addition of two numerals, <code>add2</code>, is just applying one numeral after the other, with the same increment function, to an initial value. So <code>add2( S(S(Z)) )( S(S(Z)) )</code> (2 + 2) should be equivalent to <code>S(S(S(S(Z))))</code> (4). Adding three numerals, <code>add3</code>, can be done similarly, or in terms of <code>add2</code>.</p>
<pre class="lang-js prettyprint-override"><code>const add2 =
  (m_times) =&gt; (n_times) =&gt;
    (inc) =&gt; (zero) =&gt; m_times(inc)(n_times(inc)(zero));

const add3 =
  (x) =&gt; (y) =&gt; (z) =&gt; add2(x)(add2(y)(z));
</code></pre>
<p>Now we can make a few constants, or a conversion from JavaScript’s native <code>Number</code> type, as well as an example expression.</p>
<pre class="lang-js prettyprint-override"><code>const one = S(Z);
const two = S(one);
const three = S(two);

function from_number(x) {
  let n = Z;
  for (let i = 0; i &lt; x; ++i) {
    n = S(n);
  }
  return n;
}

const one_plus_two_plus_three = add3(one)(two)(three);
</code></pre>
<p>We can test that the example term gives the right answer by converting it back to a printable type such as <code>Number</code>.</p>
<pre class="lang-js prettyprint-override"><code>const number_zero = 0;
const number_inc = (x) =&gt; x + 1;
const to_number = (n) =&gt; n(number_inc)(number_zero);

console.log(to_number(one_plus_two_plus_three));
</code></pre>
<p>In general, any target type will work, since numerals are polymorphic. Here’s a conversion of the numeral <em>n</em> to a <code>String</code> of <em>n</em> asterisks.</p>
<pre class="lang-js prettyprint-override"><code>const asterisk_zero = &quot;&quot;;
const asterisk_inc = (x) =&gt; x + &quot;*&quot;;
const to_asterisk = (n) =&gt; n(asterisk_inc)(asterisk_zero);

console.log(to_asterisk(one_plus_two_plus_three));
</code></pre>

CC BY-SA 4.0
2023-11-24T17:36:18.910Z
2023-11-28T20:59:15.160Z
2023-11-28T20:59:15.160Z
Jon Purdy
CC BY-SA 4.0
2023-11-25T20:08:13.267Z
**Comments have been [moved to chat](https://chat.stackexchange.com/rooms/149913/discussion-on-answer-by-jon-purdy-how-to-implement-in-a-language-where-functio); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.
Michael Homer
CC BY-SA 4.0
2023-11-26T10:03:37.797Z
I allowed myself to extend your example a bit, to make it more obvious what is part of the Church encoding and what is not. And now I am wondering if the Church encoding is just another fancy way of cheating. Because the actual addition happens in the incrementation. But the Church encoding does not say anything about the incrementation, it just uses it as a parameter.
ceving
CC BY-SA 4.0
2023-11-27T20:34:35.100Z
@ceving Maybe `const number_inc = (x) => ++x ` would be clearer? There's no two-operand addition needed, just a rule that can take any number, and return the "next" number.
IMSoP
<p>I think this comment from <a href="https://langdev.stackexchange.com/users/867/benrg">benrg</a> is a useful insight:</p>
<blockquote>
<p>There is a binary operator in lambda calculus, namely function application. You could argue that it's a two-argument function.</p>
</blockquote>
<p>In other words, we can express anything in the form <code>apply(function, argument)</code> by carefully choosing values for <code>function</code> and <code>argument</code>.</p>
<p>In the expression <code>1 + 3</code>, we have <em>three</em> pieces of information: the operator/function <code>add</code>, and the numerals <code>1</code> and <code>3</code>. If we had a function <code>apply(function, argument1, argument2)</code>, we could write <code>apply(add, 2, 3)</code>. But if we have only <code>apply(function, argument)</code>, where does the extra piece of information go?</p>
<p>The answer is <em>into the definition of <code>function</code></em>: instead of <code>add</code>, we define a function <code>add2</code>, so that we can write <code>apply(add2, 3)</code>.</p>
<hr />
<p>Let's start by defining <code>add1</code>. If you only need to handle a finite set of numbers, you can do this with an exhaustive lookup table. In Haskell, you could do this with pattern matching; in JavaScript, you could use a <code>switch</code> statement:</p>
<pre><code>add1 = (n) =&gt; { 
    switch(n) {
        case 0: return 1;
        case 1: return 2;
        case 2: return 3;
        // etc
    }
}
</code></pre>
<p>We could use the same technique to write <code>add2</code>, <code>add3</code>, and so on; but actually we don't need to if we realise that adding 2 is the same as adding 1, then adding 1 again. In other words, given a definition of <code>add1</code>, we can do this:</p>
<pre><code>add2 = (n) =&gt; add1(add1(n));
add3 = (n) =&gt; add1(add1(add1(n)));
// etc
</code></pre>
<p>The only extra case we need is <code>add0</code>, which just returns its input unchanged. This is known as the &quot;identity function&quot;:</p>
<pre><code>identity = (x) =&gt; x
add0 = identity
</code></pre>
<p>To add <em>any</em> pair of numbers, we need a function which takes a number, and returns a function which adds that number: for the input <code>2</code>, return the function <code>add2</code>, and so on. Again, a simple implementation could use a lookup table:</p>
<pre><code>add = (m) =&gt; {
    switch(m) {
       case 0: return add0;
       case 1: return add1;
       case 2: return add2;
       case 3: return add3;
       // ...
    }
}
</code></pre>
<p>So now, without ever defining 2-ary addition directly, we have our curried implementation:</p>
<pre><code>add(2)(3);
</code></pre>
<hr />
<p>There's various ways we can take this further. One is by deciding the pattern of repeatedly applying <code>add1</code> is something we might want to use with other functions. So we could write some helpers which take a function, and return a new function applying it multiple times:</p>
<pre><code>repeat2 = (func) =&gt; (x) =&gt; func(func(x))
add2 = repeat2(add1)
</code></pre>
<p>As before, there are some special cases to consider:</p>
<ul>
<li><code>repeat0</code> needs to ignore the function passed to it, and use a function that &quot;does nothing&quot; in its place: the <code>identity</code> function we defined earlier. In other words, <code>repeat0(anything)(n)</code> will reduce to <code>identity(n)</code>, which is just <code>n</code>.</li>
<li><code>repeat1</code> could be written the same way as the others, as <code>(func) =&gt; (x) =&gt; func(x)</code>, but <code>(x) =&gt; func(x)</code> is equivalent to <code>func</code>. That leaves <code>(func) =&gt; func</code>, which is just <code>identity</code> again. That makes sense: repeating something once is the same as just doing the thing.</li>
</ul>
<pre><code>repeat0 = (func) =&gt; identity
repeat1 = identity
</code></pre>
<p>Then, just as we did for <code>add</code>, we can write a general <code>repeat</code> function which takes a number, and returns an appropriate <code>repeatN</code> function:</p>
<pre><code>repeat = (times) =&gt; {
    switch (times) {
        case 0: return repeat0;
        case 1: return repeat1;
        case 2: return repeat2;
        case 3: return repeat3;
        // ...
    }
}
</code></pre>
<p>Or, if we skip the separate named functions, and put everything into <code>repeat</code> itself:</p>
<pre><code>repeat = (times) =&gt; {
    switch (times) {
        case 0: return (func) =&gt; identity;
        case 1: return identity;
        case 2: return (func) =&gt; (x) =&gt; func(func(x));
        case 3: return (func) =&gt; (x) =&gt; func(func(func(x)));
        // ...
    }
}
</code></pre>
<p>Now we can simplify our definitions of <code>add2</code>, <code>add3</code>, etc:</p>
<pre><code>add2 = repeat(2)(add1)
add3 = repeat(3)(add1)
</code></pre>
<p>Another thing we can do is skip the named definitions of <code>add2</code>, <code>add3</code>, etc and move their definitions inside <code>add</code> itself:</p>
<pre><code>add = (m) =&gt; {
    switch(m) {
       case 0: return identity;
       case 1: return add1;
       case 2: return repeat(2)(add1);
       case 3: return repeat(3)(add1);
       // ...
    }
}
</code></pre>
<p>But hang on, we know that <code>repeat(0)(add1)</code> is <code>identity</code>, and <code>repeat(1)(add1)</code> is <code>add1</code></p>
<p>So we don't actually need the lookup table any more, we can just use <code>repeat</code>:</p>
<pre><code>add = (m) =&gt; repeat(m)(add1)
</code></pre>
<p>So we've defined <code>add</code> based on just three functions: <code>identity</code>, <code>repeat</code>, and <code>add1</code>.</p>
<hr />
<p>We can carry on further if we want to: <a href="https://en.wikipedia.org/wiki/Church_encoding" rel="nofollow noreferrer">Church encoding</a> gives definitions for both <code>add1</code> (a <a href="https://en.wikipedia.org/wiki/Successor_function" rel="nofollow noreferrer">successor function</a>) and <code>repeat</code> using recursive application of a single function, rather than a lookup table.</p>

CC BY-SA 4.0
2023-11-25T19:51:20.857Z
2023-11-26T00:00:38.110Z
2023-11-26T00:00:38.110Z
IMSoP
CC BY-SA 4.0
2023-11-27T18:40:10.083Z
**Comments have been [moved to chat](https://chat.stackexchange.com/rooms/149950/discussion-on-answer-by-imsop-how-to-implement-in-a-language-where-functions-a); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.
Michael Homer
# How to implement + in a language where functions accept only one argument?
Posted by: username_0 on 2023-11-24
While reading about currying, I found the argument that it is beneficial in languages, which have only functions accepting only one argument.
I am wondering how to implement a 2-ary function like the addition in a language having only 1-ary functions?
The cited blog gives the following example:
function threeArity(x: number, y: number, z: number): number {
    return x + y + z;
}

function curriedThree(x: number): (y: number) => ((z: number) => number) {
    return function (y: number): (z: number) => number {
        return function (z: number): number {
            return x + y + z;
        }
    }
}

console.log(threeArity(1, 2, 3));
console.log(curriedThree(1)(2)(3));

But I think this is cheating, because in the end the 2-ary + is used.  If the language has only 1-ary functions such a 2-ary + can not exist. How would a 1-ary addition look like?
**Tags:** functional-programming currying
> **Comments:**
> **username_1**: You can go as deep down the rabbit hole as you like. The answers go as far as Church encoding. If you're interested in the abstract details of the bit, then there's your answer. If you're interested in doing currying in a practical programming language, then using a bootstrapped or built-in `+` is your answer.  
> **username_2**: I don't understand this as a question about language design or implementation. When you implement a programming language, you generally do so in a different language (the host language). So even if your language doesn't support 2-ary functions or operators, you can still implement your curried "plus" function using the host language's `+` operator.  
> **username_3**: @kaya3, the point is that you can't self-express the fundamentals of the language, following your logic. Obviously, a simplistic and limited language can always be expressed by calling into a more fundamental and more complete language. A language considering only of 1-adic functions is a simplistic and limited language, which is either computationally useless, or it is implemented in terms of a much more complicated assembly language (i.e. it relies on causing certain computations to occur which cannot be expressed in the language itself).  
> **username_2**: @Steve That's not a language design or implementation problem, though. In practice a language doesn't need to self-express its own native operations (including addition), they are implemented in some other language, or ultimately implemented by logic gates in hardware.  
> **username_3**: @kaya3, it's a problem for those who are trying to discern whether they've understood a particular language correctly, and whether a particular language incorporates concepts that can cope with all essential aspects of what a computer *does*. Even hardware gates have multiple inputs as standard. The purpose of questions like these is not to understand languages in their own terms - it is to establish whether a particular language is fit to be integrated into an all-encompassing mental model. So what the language claims to do has to reconcile globally within your own understanding. (1/2)  
> **username_3**: The purpose of this reconciliation is to drive out contradiction. The OP has clearly got the impression that all computation can be modelled with only 1-adic functions. I'm as interested in that question as he is, and that claim doesn't in fact seem to be true. Like him, I can't seem to find a logic where you don't need to operate on two values at once, in order to implement addition. This simultaneous presence of two values seems irreducible, and cannot be expressed as a series of operations on just one value each turn. (2/2)  
> **username_4**: @Steve: Formally, currying implies pairs; Cartesian-closed categories have products whenever they have exponentials. I'm not sure whether this would be an acceptable answer, but it is certainly the formal answer.  
> **username_2**: @Steve Questions about understanding how real languages work (e.g. Haskell or F# both only have unary functions) are better suited for Stack Overflow, or if it's about what's theoretically possible with only unary functions/lambda calculus then one of [Computer Science](https://cs.stackexchange.com/) or [CS Theory](https://cstheory.stackexchange.com/) would seem to be the appropriate venue. As I said, I don't see how this question is about language design or implementation.  
> **username_2**: [This question is being discussed on meta.](https://langdev.meta.stackexchange.com/q/614/89)  
> **username_5**: I mentioned this in one of the comment rooms, but I thought the original asker might find this helpful. I made an implementation of a language that only has single argument functions, function application and a print function. I have a web-based REPL where you can use it with your browser [here](https://roboguy13.github.io/utlc-eval/), along with a bunch of examples. I have numbers implemented as Church numerals. For example, if you try `mult two three (print a) id` it will print `a` six times. As the implementor, I can tell you there are no multi-argument functions in the language.  
> **username_5**: It also has a REPL command that will compile an expression to Python. The Python code will be a huge monstrosity but if you look carefully you will note: Even in this compiled version, not a multi-argument function (or tuple, etc) in sight!  
---
## 3 answers
### Answer by username_8 on 2023-11-24. Score: 12
I think this is cheating, because in the end the 2-ary + is used.
If the language has only 1-ary functions such a 2-ary + can not exist.

Not so—in GHC Haskell, the primitive operations are still defined with curried function types. For instance, the unboxed integer addition operator is this: (+#) :: Int# -> Int# -> Int#. If you apply it to two operands, it can compile directly to an addition instruction; but you can also allocate a closure by applying it to only one operand.
In JavaScript, of course that isn’t the case: the curried function needs to be defined in terms of the binary + operator. However, it’s worth noting that in JavaScript and many other languages, this is a primitive binary operation that isn’t a function.
In a similar vein, Haskell’s tuple type can be constructed with a function (,) :: a -> b -> (a, b), or with built-in tuple syntax, which has its own typing rule unrelated to functions: (e1, e2) :: (A, B) if e1 :: A and e2 :: B.

How would a 1-ary addition look like?

If we don’t have any primitive binary operations like addition, we might still implement it using only a unary increment operation. But supposing we didn’t even have that, we could still construct it using Church encoding.
Numerals are made from the zero numeral Z and the successor function S. A numeral has two parameters: an “increment” function for the inductive case, and an initial “zero” value for the base case. Its numeric value is encoded implicitly, in unary, by the number of times that it applies the function to the value. For example, 2 is S(S(Z)).
const Z =
  (inc) => (zero) => zero;

const S =
  (n_times) =>
    (inc) => (zero) => inc(n_times(inc)(zero));

The addition of two numerals, add2, is just applying one numeral after the other, with the same increment function, to an initial value. So add2( S(S(Z)) )( S(S(Z)) ) (2 + 2) should be equivalent to S(S(S(S(Z)))) (4). Adding three numerals, add3, can be done similarly, or in terms of add2.
const add2 =
  (m_times) => (n_times) =>
    (inc) => (zero) => m_times(inc)(n_times(inc)(zero));

const add3 =
  (x) => (y) => (z) => add2(x)(add2(y)(z));

Now we can make a few constants, or a conversion from JavaScript’s native Number type, as well as an example expression.
const one = S(Z);
const two = S(one);
const three = S(two);

function from_number(x) {
  let n = Z;
  for (let i = 0; i < x; ++i) {
    n = S(n);
  }
  return n;
}

const one_plus_two_plus_three = add3(one)(two)(three);

We can test that the example term gives the right answer by converting it back to a printable type such as Number.
const number_zero = 0;
const number_inc = (x) => x + 1;
const to_number = (n) => n(number_inc)(number_zero);

console.log(to_number(one_plus_two_plus_three));

In general, any target type will work, since numerals are polymorphic. Here’s a conversion of the numeral n to a String of n asterisks.
const asterisk_zero = "";
const asterisk_inc = (x) => x + "*";
const to_asterisk = (n) => n(asterisk_inc)(asterisk_zero);

console.log(to_asterisk(one_plus_two_plus_three));
> **Comments:**
> **username_7** (2023-11-25): **Comments have been [moved to chat](https://chat.stackexchange.com/rooms/149913/discussion-on-answer-by-jon-purdy-how-to-implement-in-a-language-where-functio); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.  
> **username_0** (2023-11-26): I allowed myself to extend your example a bit, to make it more obvious what is part of the Church encoding and what is not. And now I am wondering if the Church encoding is just another fancy way of cheating. Because the actual addition happens in the incrementation. But the Church encoding does not say anything about the incrementation, it just uses it as a parameter.  
> **username_9** (2023-11-27): @ceving Maybe `const number_inc = (x) => ++x ` would be clearer? There's no two-operand addition needed, just a rule that can take any number, and return the "next" number.  
---
### Answer by username_9 on 2023-11-25. Score: 5
I think this comment from benrg is a useful insight:

There is a binary operator in lambda calculus, namely function application. You could argue that it's a two-argument function.

In other words, we can express anything in the form apply(function, argument) by carefully choosing values for function and argument.
In the expression 1 + 3, we have three pieces of information: the operator/function add, and the numerals 1 and 3. If we had a function apply(function, argument1, argument2), we could write apply(add, 2, 3). But if we have only apply(function, argument), where does the extra piece of information go?
The answer is into the definition of function: instead of add, we define a function add2, so that we can write apply(add2, 3).

Let's start by defining add1. If you only need to handle a finite set of numbers, you can do this with an exhaustive lookup table. In Haskell, you could do this with pattern matching; in JavaScript, you could use a switch statement:
add1 = (n) => { 
    switch(n) {
        case 0: return 1;
        case 1: return 2;
        case 2: return 3;
        // etc
    }
}

We could use the same technique to write add2, add3, and so on; but actually we don't need to if we realise that adding 2 is the same as adding 1, then adding 1 again. In other words, given a definition of add1, we can do this:
add2 = (n) => add1(add1(n));
add3 = (n) => add1(add1(add1(n)));
// etc

The only extra case we need is add0, which just returns its input unchanged. This is known as the "identity function":
identity = (x) => x
add0 = identity

To add any pair of numbers, we need a function which takes a number, and returns a function which adds that number: for the input 2, return the function add2, and so on. Again, a simple implementation could use a lookup table:
add = (m) => {
    switch(m) {
       case 0: return add0;
       case 1: return add1;
       case 2: return add2;
       case 3: return add3;
       // ...
    }
}

So now, without ever defining 2-ary addition directly, we have our curried implementation:
add(2)(3);


There's various ways we can take this further. One is by deciding the pattern of repeatedly applying add1 is something we might want to use with other functions. So we could write some helpers which take a function, and return a new function applying it multiple times:
repeat2 = (func) => (x) => func(func(x))
add2 = repeat2(add1)

As before, there are some special cases to consider:

repeat0 needs to ignore the function passed to it, and use a function that "does nothing" in its place: the identity function we defined earlier. In other words, repeat0(anything)(n) will reduce to identity(n), which is just n.
repeat1 could be written the same way as the others, as (func) => (x) => func(x), but (x) => func(x) is equivalent to func. That leaves (func) => func, which is just identity again. That makes sense: repeating something once is the same as just doing the thing.

repeat0 = (func) => identity
repeat1 = identity

Then, just as we did for add, we can write a general repeat function which takes a number, and returns an appropriate repeatN function:
repeat = (times) => {
    switch (times) {
        case 0: return repeat0;
        case 1: return repeat1;
        case 2: return repeat2;
        case 3: return repeat3;
        // ...
    }
}

Or, if we skip the separate named functions, and put everything into repeat itself:
repeat = (times) => {
    switch (times) {
        case 0: return (func) => identity;
        case 1: return identity;
        case 2: return (func) => (x) => func(func(x));
        case 3: return (func) => (x) => func(func(func(x)));
        // ...
    }
}

Now we can simplify our definitions of add2, add3, etc:
add2 = repeat(2)(add1)
add3 = repeat(3)(add1)

Another thing we can do is skip the named definitions of add2, add3, etc and move their definitions inside add itself:
add = (m) => {
    switch(m) {
       case 0: return identity;
       case 1: return add1;
       case 2: return repeat(2)(add1);
       case 3: return repeat(3)(add1);
       // ...
    }
}

But hang on, we know that repeat(0)(add1) is identity, and repeat(1)(add1) is add1
So we don't actually need the lookup table any more, we can just use repeat:
add = (m) => repeat(m)(add1)

So we've defined add based on just three functions: identity, repeat, and add1.

We can carry on further if we want to: Church encoding gives definitions for both add1 (a successor function) and repeat using recursive application of a single function, rather than a lookup table.
> **Comments:**
> **username_7** (2023-11-27): **Comments have been [moved to chat](https://chat.stackexchange.com/rooms/149950/discussion-on-answer-by-imsop-how-to-implement-in-a-language-where-functions-a); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.  
---
### Answer by username_6 on 2023-11-24. Score: 3
Assuming a functional language with currying and only unary functions where `add` implements addition:

* `add` has type `int -> (int -> int)`
* `add 5` returns an (anonymous) unary function that adds 5 to its argument
* `(add 5) 7` would apply this function to `7` - resulting in `12`.

Usually the parentheses are not written explicitly because `->` is right associative and function application is left associative.

Transforming `x + y` into `add x y` is purely syntactical and is performed by the parser of the language.
> **Comments:**
> **username_7** (2023-11-25): **Comments have been [moved to chat](https://chat.stackexchange.com/rooms/149900/discussion-on-answer-by-christian-lindig-how-to-implement-in-a-language-where); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.  
---
