#include <stdio.h>
#include <functional>

using namespace std;

template<typename A, typename B>
using F = function<A(B)>;

template<typename A>
using CN = F<F<A, A>, F<A, A>>;

template<typename A>
CN<A> zero() {
 return [](F<A,A>) -> F<A,A> {
    return [](A i) -> A {return i;};
 };
}

template<typename A>
CN<A> inc(CN<A> n) {
    return [=](F<A,A> f) -> F<A,A> {
        return [=](A a) -> A {
            return n(f)(f(a));
        };
    };
}

template<typename A>
CN<A> operator*(CN<A> a, CN<A> b) {
    return [=](F<A,A> f) -> F<A,A> {
        return b(a(f));
    };
}

template<typename A>
CN<A> operator+(CN<A> a, CN<A> b) {
    return [=](F<A,A> f) -> F<A,A> {
        return [=](A i) -> A {
            auto i1 = a(f)(i);
            return b(f)(i1);
        };
    };
}

CN<unsigned int> i2c(unsigned int n) {
	auto l = zero<unsigned int>();
	for(int i = 0; i<n; i++)
		l = inc(l);
	return l;
}

unsigned int c2i(CN<int> n) {
    auto n2 = n([&](int a)->int {return a+1;});
    return n2(0);
}

int multiply(unsigned int a, unsigned int b) {
	return c2i(i2c(a) * i2c(b));
}

int main() {
	unsigned int a, b;
	a = 4;
	b = 3;
	printf("%d*%d=%d", a, b, multiply(a, b));
	return 0;
}