【问题标题】:C++ Concepts: Can I define a concept that is itself a template?C++ 概念:我可以定义一个本身就是模板的概念吗?
【发布时间】:2016-04-12 18:07:22
【问题描述】:

抱歉,如果问题不太清楚。我不确定表达它的最佳方式(随意编辑!)。我认为一个例子是最清楚的:

我试图根据Haskell definition 定义一个 Monad 概念。绑定运算符 (>>=) 要求 Monad 类型为 A 的函数可以绑定到接受 A 并返回 Monad 类型为 B 的函数。我可以根据value_type typedef 定义A,但是如何在我的概念中定义类型B

template <typename M>
concept bool Monad()
{
  return requires(M m, Function<_1, ValueType<M>> f) {
    // (>>=) :: m a -> (a -> m b) -> m b
    { m >>= f } -> M
  }
}

在上面的例子中,我应该用什么来代替 Function 概念中的_1

这是否也足以将调用 f 的结果限制为任何类型的 Monad?

【问题讨论】:

  • 顺便说一句,(ab)在这里使用operator&gt;&gt;= 似乎是一个错误。在 C++ 中,a &gt;&gt;= b &gt;&gt;= c 关联为 a &gt;&gt;= (b &gt;&gt;= c),而在 Haskell 中,它关联为 (a &gt;&gt;= b) &gt;&gt;= c
  • 是的,我知道 :) 显然不是值得生产的代码——只是玩游戏来学习一些概念

标签: c++ generic-programming c++17 c++-concepts


【解决方案1】:

我认为您可以做的最接近的可能是提供一个 特定 函数 A --&gt; Monad&lt;B&gt; 并验证它是否正确。为了防止无限递归,我们可以验证A --&gt; M 是否有效:

template <class M>
concept bool Monad()
{
    return requires(M m) {
        { m >>= std::function<M(ValueType<M>)>{} } -> M;
    };
}

这只是一种特定情况,但我认为不可能验证A --&gt; Monad&lt;X&gt; 工作的一般情况,因为概念检查仍然涉及特定表达式,您只能创建具有特定类型的特定表达式。

当然,我们可以提供多个这样的要求。使用重新绑定元函数:

template <class M, class X>
struct rebind;

template <class M, class X>
using rebind_t = typename rebind<M, X>::type;

template <template <class...> class Z, class R, class X>
struct rebind<Z<R>, X> {
    using type = Z<X>;
};

然后我们可以为返回各种类型的函数添加要求,比如说它也适用于ints:

template <class M>
concept bool Monad()
{
    return requires(M m)
    {
        { m >>= std::function<M(ValueType<M>)>{} } -> M;
        { m >>= std::function<rebind_t<M,int>(ValueType<M>)>{} } -> rebind_t<M,int>;
    };
}

将其重构为自己的子概念可能会变得更容易:

template <class M, class R>
concept bool MonadBind()
{
    return requires(M m) {
        { m >>= std::function<rebind_t<M,R>(ValueType<M>)>{} } -> rebind_t<M,R>;
    };
}

template <class M>
concept bool Monad()
{
    return requires(M m) {
        requires MonadBind<M, ValueType<M>>();
        requires MonadBind<M, int>();
    };
}

【讨论】:

    猜你喜欢
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    相关资源
    最近更新 更多