所以我在玩 GCC6 及其概念实现,我认为 Haskell Prelude 将是一个很好的实验来源。Haskell 的核心特性之一是函数组合,这是我需要立即解决的问题。
尽我所能模仿 Haskell 语法,我写了这个函数:
template <typename F, typename G>
auto operator*(F f, G g)
{
return [f, g](auto... args) {
return f(g(args...));
}
}
效果很好,让我可以做以下事情:
auto add([](int a, int b) { return a + b; }
auto doubled([](int a) { return a * 2; }
auto add_then_double(doubled * add);
assert(add_then_double(2, 3) == 10);
很高兴,我决定回去对我的函数组合应用一些约束,但由于它的懒惰,我很快遇到了一个问题。
首先我写了这个概念:
template <typename F, typename Ret, typename... Args>
concept bool Function()
{
return requires(F f, Args ...args) {
{ f(args...) } -> Ret;
}
}
我基于Andrew Sutton 的原始github 项目中的概念。
所以我试图应用到我原来的功能。我遇到的问题是我不知道G
返回什么而不知道传递给什么参数,G
所以我无法约束G
,我不知道F
返回什么而不知道它给出了什么参数,我不知道,因为我不知道G
返回什么。
我很确定我需要一个Function
不关心返回类型的新概念,因为我的组合函数不关心F
返回什么,只要它是可调用的。而且我想我可以对内部 lambda 进行约束,即参数类型并更正 G 和 F 但这意味着我可以编写不可组合的函数并且在调用站点之前不会出错。这是可以避免的吗?
也许是这样的:
template <typename F, typename G>
auto operator*(F f, G g)
{
return [f, g](auto... args)
// is it even possible to constrain here?
requires FunctionAnyReturn<G, decltype(args)...>
&& FunctionAnyReturn<F, decltype(G(decltype(args)...))>
{
return f(g(args...));
}
}
这是我能做的最好的吗(如果我能做到的话)?