user
Task

In the Church encoding of natural numbers, the number N is encoded by a function that applies its first argument N times to its second argument.

* **Church zero** always returns the identity function, regardless of its first argument. In other words, the first argument is not applied to the second argument at all.
* **Church one** applies its first argument f just once to its second argument x, yielding **f(x)**
* **Church two** applies its first argument f twice to its second argument x, yielding **f(f(x))**
* and each successive Church numeral applies its first argument one additional time to its second argument, **f(f(f(x)))**, **f(f(f(f(x))))** ... The Church numeral 4, for example, returns a quadruple composition of the function supplied as its first argument.

Arithmetic operations on natural numbers can be similarly represented as functions on Church numerals.

In your language define:

* Church Zero,
* a Church successor function (a function on a Church numeral which returns the next Church numeral in the series),
* functions for Addition, Multiplication and Exponentiation over Church numerals,
* a function to convert integers to corresponding Church numerals,
* and a function to convert Church numerals to corresponding integers.

You should:

* Derive Church numerals three and four in terms of Church zero and a Church successor function.
* use Church numeral arithmetic to obtain the the sum and the product of Church 3 and Church 4,
* similarly obtain 4^3 and 3^4 in terms of Church numerals, using a Church numeral exponentiation function,
* convert each result back to an integer, and return it or print it to the console.
assistant
(formerly Perl 6)

### Traditional subs and sigils

**Translation of**: Python

```
constant $zero  = sub (Code $f) {
                  sub (     $x) { $x }}

constant $succ  = sub (Code $n) {
                  sub (Code $f) {
                  sub (     $x) { $f($n($f)($x)) }}}

constant $add   = sub (Code $n) {
                  sub (Code $m) {
                  sub (Code $f) {
                  sub (     $x) { $m($f)($n($f)($x)) }}}}

constant $mult  = sub (Code $n) {
                  sub (Code $m) {
                  sub (Code $f) {
                  sub (     $x) { $m($n($f))($x) }}}}

constant $power = sub (Code $b) {
                  sub (Code $e) { $e($b) }}

sub to_int (Code $f) {
    sub countup (Int $i) { $i + 1 }
    return $f(&countup).(0)
}

sub from_int (Int $x) {
    multi sub countdown (     0) { $zero }
    multi sub countdown (Int $i) { $succ( countdown($i - 1) ) }
    return countdown($x);
}

constant $three = $succ($succ($succ($zero)));
constant $four  = from_int(4);

say map &to_int,
    $add(   $three )( $four  ),
    $mult(  $three )( $four  ),
    $power( $four  )( $three ),
    $power( $three )( $four  ),
;

```

### Arrow subs without sigils

**Translation of**: Julia

```
my \zero  = -> \f {                 -> \x { x               }}
my \succ  = -> \n {         -> \f { -> \x { f.(n.(f)(x))    }}}
my \add   = -> \n { -> \m { -> \f { -> \x { m.(f)(n.(f)(x)) }}}}
my \mult  = -> \n { -> \m { -> \f { -> \x { m.(n.(f))(x)    }}}}
my \power = -> \b {                 -> \e { e.(b)           }}

my \to_int   = -> \f { f.( -> \i { i + 1 } ).(0) }
my \from_int = -> \i { i == 0 ?? zero !! succ.( &?BLOCK(i - 1) ) }

my \three = succ.(succ.(succ.(zero)));
my \four  = from_int.(4);

say map -> \f { to_int.(f) },
    add.(   three )( four  ),
    mult.(  three )( four  ),
    power.( four  )( three ),
    power.( three )( four  ),
;

```

Output:

```
(7 12 64 81)
```