【问题标题】:Implementing the (typed) K combinator in C++在 C++ 中实现(类型化的)K 组合子
【发布时间】:2016-02-15 07:19:11
【问题描述】:

我正在尝试在 C++ 中实现来自 SK combinator calculus 的 K 组合子。 K 组合器是一个higher-order function,它基本上取一些值x,并返回一些东西,反过来取一个值y 并从中返回x。换句话说,

K(x)(y) == x

或一步一步:

intermediate = K(x)
intermediate(y) == x

K(x) 视为独立于y 的事物本身的能力至关重要。此外,在简单地创建K(x) 而不在y 上调用它时,不必指定y 的类型。 y 的类型可以在代码中某处被评估 K(x)(y) 时指定。

我正在尝试修复我编写的尝试实现 K 组合器的代码:

#include <iostream>

template<class A>
template<class B>
auto K = [](A x) {
    return [=](B y) {
        return x;
    };
};

int main()
{
    std::cout << "Hello world!\n";
    auto Kx = K<int>(3);
    auto Kxy = Kx<float>(4.5);
    std::cout << Kxy << std::endl;
}

它输出error: extraneous template parameter list in template specialization or out-of-line template definition。我尝试调整模板参数并移动它们无济于事。有谁知道我该如何解决这个错误?

【问题讨论】:

    标签: c++ templates metaprogramming functor higher-order-functions


    【解决方案1】:

    Lambda 不能是模板。你可以这样做:

    #include <iostream>
    
    auto K = [](auto x) {
        return [=](auto y) {
            return x;
        };
    };
    
    int main()
    {
        std::cout << "Hello world!\n";
        auto Kx = K(3);
        auto Kxy = Kx(4.5);
        std::cout << Kxy << std::endl;
    }
    

    这些被称为通用 lambdas(自 C++14 起就存在),基本上就是你想要的。他们的operator() 是每个auto 参数的模板。

    【讨论】:

    • 您可以在 C++14 中使用模板化变量。您可能还想补充一点,泛型 lambda 也是 C++14 的一部分。
    • @JoachimPileborg 这是另一回事。
    【解决方案2】:

    即使您没有 C++14,这也很有可能——请记住 lambda 只是仿函数对象的一种快捷表示法。因此,我们可以创建一个表示中间值的对象:

    template<class A>
    class Intermediate {
      A m_a;
    public:
      explicit Intermediate(const A& a)
      : m_a(a)
      {}
    
      template<class B>
      A operator()(const B&) const
      { return m_a; }
    };
    
    template<class A>
    Intermediate<A> K(const A& a)
    { return Intermediate<A>(a); }
    

    模板参数推导需要单独的K函数,以便我们可以编写K(x)(y)

    【讨论】:

      【解决方案3】:

      您可以通过以下更改“解决”它:

      template<class A, class B>
      auto K = [](A x) {
          return [=](B y) {
              return x;
          };
      };
      

      但是,您还需要更改调用:

      auto Kx = K<int, float>(3);
      auto Kxy = Kx(4.5);
      

      作为一个解释说明,虽然 lambdas 本身不能被模板化,但从 C++14 变量可以,而且我正在做的是将 K 声明为模板化变量,恰好该变量是声明为 lambda 对象。

      【讨论】:

      • 这个语法是真的吗? ideone.com/gjWyf5你应该看看尤里的回答。
      • @xaxxon Yuri 的答案更好,这就是我投票支持它的原因,但这在使用旧的 clang 编译器的 C++14 中运行良好。可能是clang中的错误,或者可能是ideone上的GCC中的错误,我不知道。
      猜你喜欢
      • 2020-06-21
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      • 2012-01-22
      • 2019-09-21
      • 2021-11-24
      • 2023-03-19
      • 1970-01-01
      相关资源
      最近更新 更多