在C ++中实现(类型化)K组合器

时间:2016-02-15 07:19:12

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

我正在尝试从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的事物本身的能力至关重要。此外,在y上调用K(x)而不调用y时,无需指定y的类型。在代码中的某处评估K(x)(y)后,可以指定#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; } 的类型。

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

error: extraneous template parameter list in template specialization or out-of-line template definition

输出float[] coordinates = {x, y};。我试过调整模板参数并移动它们无济于事。有谁知道如何解决这个错误?

3 个答案:

答案 0 :(得分:8)

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

#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;
}

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

答案 1 :(得分:2)

即使你没有C ++ 14,也很有可能 - 只记得lambdas只是functor对象的快捷符号。因此,我们可以创建一个表示中间值的对象:

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)

答案 2 :(得分:1)

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

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对象。