church_encoding C++版实现

这篇博客介绍了如何在C++中实现Church编码,包括布尔类型和数值类型的转换及基本操作,如加减乘除、逻辑运算。还展示了Church列表的Cons、Car和Cdr操作。然而,文章提到对于涉及递归的除法和取余操作,由于当前的If结构,可能会导致无限递归和内存溢出问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值