C++ 中的定点组合器

发布于 2024-07-05 16:25:05 字数 894 浏览 9 评论 0原文

我对使用定点组合器的实际示例感兴趣(例如 y-combinator 中C++。您是否曾经使用过 鸡蛋绑定 在真实的代码中?

我发现 Egg 中的这个例子有点密集:

void egg_example()
{
    using bll::_1;
    using bll::_2;

    int r =
        fix2(
            bll::ret<int>(
                // \(f,a) -> a == 0 ? 1 : a * f(a-1)
                bll::if_then_else_return( _2 == 0,
                    1,
                    _2 * lazy(_1)(_2 - 1)
                )
            )
        ) (5);

    BOOST_CHECK(r == 5*4*3*2*1);
}

你能解释一下这一切是如何工作的吗?

是否有一个很好的简单例子,也许使用了比这个更少的依赖项?

I'm interested in actual examples of using fixed point combinators (such as the y-combinator in C++. Have you ever used a fixed point combinator with egg or bind in real live code?

I found this example in egg a little dense:

void egg_example()
{
    using bll::_1;
    using bll::_2;

    int r =
        fix2(
            bll::ret<int>(
                // \(f,a) -> a == 0 ? 1 : a * f(a-1)
                bll::if_then_else_return( _2 == 0,
                    1,
                    _2 * lazy(_1)(_2 - 1)
                )
            )
        ) (5);

    BOOST_CHECK(r == 5*4*3*2*1);
}

Can you explain how this all works?

Is there a nice simple example perhaps using bind with perhaps fewer dependancies than this one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

粉红×色少女 2024-07-12 16:25:06

这是转换为 boost::bind 的相同代码,请注意主函数中的 y 组合器及其应用位置。 我希望这有帮助。

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>

// Y-combinator compatible factorial
int fact(boost::function<int(int)> f,int v)
{
  if(v == 0)
    return 1;
  else
    return v * f(v -1);
}

// Y-combinator for the int type
boost::function<int(int)>
    y(boost::function<int(boost::function<int(int)>,int)> f)
{
  return boost::bind(f,boost::bind(&y,f),_1);
}


int main(int argc,char** argv)
{
  boost::function<int(int)> factorial = y(fact);
  std::cout << factorial(5) << std::endl;
  return 0;
}

Here is the same code converted into boost::bind notice the y-combinator and its application site in the main function. I hope this helps.

#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>

// Y-combinator compatible factorial
int fact(boost::function<int(int)> f,int v)
{
  if(v == 0)
    return 1;
  else
    return v * f(v -1);
}

// Y-combinator for the int type
boost::function<int(int)>
    y(boost::function<int(boost::function<int(int)>,int)> f)
{
  return boost::bind(f,boost::bind(&y,f),_1);
}


int main(int argc,char** argv)
{
  boost::function<int(int)> factorial = y(fact);
  std::cout << factorial(5) << std::endl;
  return 0;
}
滴情不沾 2024-07-12 16:25:06
#include <functional>
#include <iostream>

template <typename Lamba, typename Type>
auto y (std::function<Type(Lamba, Type)> f) -> std::function<Type(Type)>
{
    return std::bind(f, std::bind(&y<Lamba, Type>, f), std::placeholders::_1);
}

int main(int argc,char** argv)
{
    std::cout << y < std::function<int(int)>, int> ([](std::function<int(int)> f, int x) {
        return x == 0 ? 1 : x * f(x - 1);
    }) (5) << std::endl;
    return 0;
}
#include <functional>
#include <iostream>

template <typename Lamba, typename Type>
auto y (std::function<Type(Lamba, Type)> f) -> std::function<Type(Type)>
{
    return std::bind(f, std::bind(&y<Lamba, Type>, f), std::placeholders::_1);
}

int main(int argc,char** argv)
{
    std::cout << y < std::function<int(int)>, int> ([](std::function<int(int)> f, int x) {
        return x == 0 ? 1 : x * f(x - 1);
    }) (5) << std::endl;
    return 0;
}
会傲 2024-07-12 16:25:06

你能解释一下这一切是如何运作的吗?

fix2 是一个 y 组合器(具体来说,它是具有两个参数的函数的组合器;第一个参数是函数(用于递归的目的),第二个参数是“适当的”函数参数)。 它创建递归函数。

bll::ret(...) 似乎创建了某种形式的函数对象,其主体是

if(second arg == 0)
{
    return 1;
}
else
{
    return second arg * first arg(second arg - 1);
}

“惰性”大概是为了阻止第一个(函数)参数的无限扩展(阅读之间的区别惰性和严格 y 组合器看看为什么)。

该代码非常可怕。 拥有匿名函数固然很好,但解决 C++ 缺乏语法支持的黑客行为使它们不值得付出努力。

Can you explain how this all works?

fix2 is a y-combinator (specifically, it is a combinator for functions with two arguments; the first argument is the function (for the purpose of recursion), the second argument is a "proper" function argument). It creates recursive functions.

bll::ret(...) appears to create some form of a function object, the body of which is

if(second arg == 0)
{
    return 1;
}
else
{
    return second arg * first arg(second arg - 1);
}

The "lazy" is presumably there to stop an infinite expansion of the first (function) argument (read up on the difference between lazy and strict y combinators to see why).

The code is quite horrible. Anonymous functions are nice to have, but the hackery to work around C++'s lack of syntactic support make them not worth the effort.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文