Task: Church numerals



C#: using System;
 
public delegate Church Church(Church f);
 
public static class ChurchNumeral
{
    public static readonly Church ChurchZero = _ => x => x;
    public static readonly Church ChurchOne = f => f;
 
    public static Church Successor(this Church n) => f => x => f(n(f)(x));
    public static Church Add(this Church m, Church n) => f => x => m(f)(n(f)(x));
    public static Church Multiply(this Church m, Church n) => f => m(n(f));
    public static Church Exponent(this Church m, Church n) => n(m);
    public static Church IsZero(this Church n) => n(_ => ChurchZero)(ChurchOne);
    public static Church Predecessor(this Church n) =>
      f => x => n(g => h => h(g(f)))(_ => x)(a => a);
    public static Church Subtract(this Church m, Church n) => n(Predecessor)(m);
    static Church looper(this Church v, Church d) =>
        v(_ => v.divr(d).Successor())(ChurchZero);
    static Church divr(this Church n, Church d) =>
        n.Subtract(d).looper(d);
    public static Church Divide(this Church dvdnd, Church dvsr) =>
        (dvdnd.Successor()).divr(dvsr);
 
    public static Church FromInt(int i) =>
      i <= 0 ? ChurchZero : Successor(FromInt(i - 1));
 
    public static int ToInt(this Church ch) {
        int count = 0;
        ch(x => { count++; return x; })(null);
        return count;
    }
 
    public static void Main() {
        Church c3 = FromInt(3);
        Church c4 = c3.Successor();
        Church c11 = FromInt(11);
        Church c12 = c11.Successor();
        int sum = c3.Add(c4).ToInt();
        int product = c3.Multiply(c4).ToInt();
        int exp43 = c4.Exponent(c3).ToInt();
        int exp34 = c3.Exponent(c4).ToInt();
        int tst0 = ChurchZero.IsZero().ToInt();
        int pred4 = c4.Predecessor().ToInt();
        int sub43 = c4.Subtract(c3).ToInt();
        int div11by3 = c11.Divide(c3).ToInt();
        int div12by3 = c12.Divide(c3).ToInt();
        Console.Write($"{sum} {product} {exp43} {exp34} {tst0} ");
        Console.WriteLine($"{pred4} {sub43} {div11by3} {div12by3}");
    } 
}


Go: package main

import "fmt"

type any = interface{}

type fn func(any) any

type church func(fn) fn

func zero(f fn) fn {
    return func(x any) any {
        return x
    }
}

func (c church) succ() church {
    return func(f fn) fn {
        return func(x any) any {
            return f(c(f)(x))
        }
    }
}

func (c church) add(d church) church {
    return func(f fn) fn {
        return func(x any) any {
            return c(f)(d(f)(x))
        }
    }
}

func (c church) mul(d church) church {
    return func(f fn) fn {
        return func(x any) any {
            return c(d(f))(x)
        }
    }
}

func (c church) pow(d church) church {
    di := d.toInt()
    prod := c
    for i := 1; i < di; i++ {
        prod = prod.mul(c)
    }
    return prod
}

func (c church) toInt() int {
    return c(incr)(0).(int)
}

func intToChurch(i int) church {
    if i == 0 {
        return zero
    } else {
        return intToChurch(i - 1).succ()
    }
}

func incr(i any) any {
    return i.(int) + 1
}

func main() {
    z := church(zero)
    three := z.succ().succ().succ()
    four := three.succ()

    fmt.Println("three        ->", three.toInt())
    fmt.Println("four         ->", four.toInt())
    fmt.Println("three + four ->", three.add(four).toInt())
    fmt.Println("three * four ->", three.mul(four).toInt())
    fmt.Println("three ^ four ->", three.pow(four).toInt())
    fmt.Println("four ^ three ->", four.pow(three).toInt())
    fmt.Println("5 -> five    ->", intToChurch(5).toInt())
}