C ++ concepts. Can I define a concept that is a template in itself?

Sorry if the question is not too clear. I'm not sure if this is the best way to express this (feel free to edit!). I think the example will be most clear:

I am trying to define a Monad concept based on the Haskell definition . The bind ( >>=) operator requires that a Monadtype Acan be associated with a function that accepts Aand returns a Monadtype B. I can define typedef Ain terms value_type, but how can I define a type Bin my concept?

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

In the example above, what do I put _1in the Function <> concept instead ?

Also, does it limit the result of calling f enough to be a Monad of any type?

+4
source share
1 answer

I think the closest thing you can do is to provide a specific function A --> Monad<B>and make sure that it does the right thing. To prevent infinite recursion, we can just make sure that it A --> Mworks:

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

This is only one specific case, but I don’t think it is possible to check the general case when it works A --> Monad<X>, since concept checks are still associated with certain expressions, and you can only create specific expressions with certain types.

, . :

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

, , , int s:

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>();
    };
}
+1

All Articles