我是靠谱客的博主 辛勤绿茶,最近开发中收集的这篇文章主要介绍church_encoding C++版实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

namespace ChurBool
{
//church bool To normal bool
auto ToNormalBool = [](auto&&f)
{
    return f(true, false);
};

auto True = [](auto&&m, auto&&)
{
    return m;
};
auto False = [](auto&&, auto&&n)
{
    return n;
};
auto And = [](auto&&m, auto&&n)
{
    return m(n,m);
};
auto Or = [](auto&&m, auto&&n)
{
    return m(m,n);
};
auto Not = [](auto&&m)
{
    return [=](auto&&a, auto&&b)
    {
        return m(b,a);
    };
};
auto Xor = [=](auto&&m, auto&&n)
{
    return m(Not(n),n);
};
auto If = [](auto&&predicate)
{
    return [=](auto&&t, auto&&f)
    {
        return predicate(t, f);
    };
};
}

namespace ChurNum
{
//church number To normal number
auto ToNormalNum = [](auto&&f)
{
    return f([](int a)
    {
        return a+1;
    })(0);
};
//0
auto zero=[](auto&&)
{
    return [](auto&&x)
    {
        return x;
    };
};
//n++
auto Inc=[](auto&&n)
{
    return [=](auto&&f)
    {
        return [=](auto&&x)
        {
            return f((n(f)(x)));
        };
    };
};
//n--
auto Dec = [](auto&&n)
{
    return [=](auto&&f)
    {
        return [=](auto&&x)
        {
            return n([=](auto&&g)
            {
                return [=](auto&&h)
                {
                    return h(g(f));
                };
            })([=](auto&&)
            {
                return x;
            })([](auto&&u)
            {
                return u;
            });
        };
    };
};
//m+n
auto Add=[](auto&&m, auto&&n)
{
    return [=](auto&&f)
    {
        return [=](auto&&x)
        {
            return m(f)((n(f)(x)));
        };
    };
};
//m-n
constexpr auto Sub=[=](auto&&m, auto&&n)
{
    return [=](auto&&f)
    {
        return [=](auto&&x)
        {
            return (n(Dec))(m)(f)(x);
        };
    };
};
//m*n
auto Mul=[](auto&&m, auto&&n)
{
    return [=](auto&&f)
    {
        return [=](auto&&x)
        {
            return m(n(f))(x);
        };
    };
};
//m^n
auto Exp=[](auto&&m, auto&&n)
{
    return [=](auto&&f)
    {
        return [=](auto&&x)
        {
            return n(m)(f)(x);
        };
    };
};
using namespace ChurBool;
auto isZero = [=](auto&&n)
{
    return n([=](auto&&)
    {
        return False;
    })(True);
};
//cmp(churNum m,churNum n){return m>=n;}
auto GEQ = [=](auto&&m, auto&&n)
{
    return isZero(Sub(n,m));
};

auto EQU = [=](auto&&m, auto&&n)
{
    return And(isZero(Sub(n,m)), isZero(Sub(m,n)));
};

auto Max = [=](auto&&m, auto&&n)
{
    return If(GEQ(m,n))
           (m,
            n);
};

//    auto div=[=](auto&&m, auto&&n){return [=](auto&&f){return [=](auto&&x){return (n(sub))(m)(f)(x);};};};
//auto div = [=](auto&&m, auto&&n)
//{
//    return If(GEQ(m,n))
//            (
//                ,)
//};

//auto Remainder = [=](auto&&m, auto&&n)
//{
//    auto ret = Sub(m,n);
//    isZero(ret);
//    if(ToNormalBool(GEQ(m, n)))
//        return Remainder(Sub(m,n), n);
//    return m;
//};

}
using namespace ChurNum;
template<size_t n>
auto ToChurNum()
{
    return Inc(ToChurNum<n-1>());
}
template<>
auto ToChurNum<0>()
{
    return zero;
}
namespace ChurList
{
    auto Cons = [](auto&&x, auto&&y)
    {
        return [=](auto&&z)
        {
            return z(x,y);
        };
    };
    auto Car = [](auto&&p)
    {
        return p([](auto&&x, auto&&)
        {
            return x;
        });
    };
    auto Cdr = [](auto&&p)
    {
        return p([](auto&&, auto&&y)
        {
            return y;
        });
    };
    auto Nil = [=](auto&&)
    {
        return True;
    };
    auto isNil = [](auto&&l)
    {
        return l([](auto&&,auto&&)
        {
            return False;
        });
    };
}
int main()
{
    auto one = Inc(zero);
    auto two = ToChurNum<2>();
    auto three = Add(two, one);
    auto eighteen = Mul(two, Mul(three,three));     //2*3*3
    cout<<ToNormalNum(three)<<endl;                 //3
    cout<<ToNormalNum(eighteen)<<endl;              //18
    cout<<ToNormalNum(Exp(three,three))<<endl;      //3^3
    cout<<ToNormalNum(Dec(Exp(three,three)))<<endl; //3^3-1
    cout<<ToNormalNum(Sub(eighteen, three))<<endl;  //18-3
    using namespace ChurBool;
    cout<<boolalpha<<ToNormalBool(True)<<endl;
    cout<<boolalpha<<ToNormalBool(False)<<endl;
    cout<<boolalpha<<ToNormalBool(Xor(True,False))<<endl;
    cout<<ToNormalNum(Max(Sub(eighteen, two), Mul(zero, two)))<<endl;    //max(18-2, 0*2)
    using namespace ChurList;
    auto myPair = Cons("Cons string,",Cons(1,Nil));
    cout<<Car(myPair)<<Car(Cdr(myPair))<<endl;
}
关于division的实现,很遗憾,这里的If并没有对两个分支的求值进行特殊处理,会出现out of memory,会无限递归下去,即SICP第一章的某一题。暂时没想到好的处理方式。求余函数同理,好遗憾啊,涉及到递归的话,那个If没法单独触发某个branch。

最后

以上就是辛勤绿茶为你收集整理的church_encoding C++版实现的全部内容,希望文章能够帮你解决church_encoding C++版实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部