c++ - 模板作为概念证据的部分应用?
问题描述
我有这个概念:
template<template<typename> typename M>
struct monad {
// M<A> pure(A a)
// M<B> flatMap(M<A> ma, std::function<M<B> (A)> f) // typename B = std::invoke_result_t<F&, A const&>
static constexpr bool is_instance = false;
};
template<template<typename> typename M> concept MonadPure = requires(blackbox::A a, blackbox::B b) {
{ monad<M>::pure(a) } -> std::same_as<M<blackbox::A>>;
{ monad<M>::pure(b) } -> std::same_as<M<blackbox::B>>;
};
template<template<typename> typename M> concept MonadFlatMap = requires(M<blackbox::A> ma,
blackbox::F<blackbox::A, M<blackbox::B>> f) {
{ monad<M>::flatMap(ma, f) } -> std::same_as<M<blackbox::B>>;
};
template<template<typename> typename M> concept Monad = monad<M>::is_instance && MonadPure<M> && MonadFlatMap<M>;
我想为变压器实施它的struct monad
证据:StateT
template<template<typename> typename M, typename S, typename A> using StateT =
M<std::function<M<std::pair<S, A>>(S)>>;
由于以下内容无效:
template<template<typename> typename M, typename S>
requires Monad<M>
struct monad<template<typename A> StateT<M, S, A>> { // do stuff
我必须“部分申请” StateT
:
template<template<typename> typename M, typename S>
struct PartiallyAppliedStateT {
template<typename A>
struct _Apply {
typedef StateT<M, S, A> type;
};
template<typename A>
using Apply = typename _Apply<A>::type;
};
template<template<typename> typename M, typename S>
requires Monad<M>
struct monad<PartiallyAppliedStateT<M, S>::Apply> { // do stuff
然而,这给我留下了一个错误:
error: type/value mismatch at argument 1 in template parameter list for 'template<template<class> class M> struct monad'
57 | struct monad<PartiallyAppliedStateT<M, S>::Apply> {
| ^
note: expected a class template, got 'PartiallyAppliedStateT<M, S>::Apply'
我怎样才能使部分应用程序 a class
,就像我认为 G++ 要求的那样?还是有更好的方法来制作StateT
单子?
G++ 版本 10.1.0 与-std=c++20
.
更正monad
定义后:
template<template<typename> typename M, typename S>
requires Monad<M>
struct monad<PartiallyAppliedStateT<M, S>::template Apply> {
我可以这样描述一个函数:
template<template<typename> typename M>
requires Monad<M>
StateT<M, long, long> nextLong() {
return monad<M>::pure([](long seed) {
long next = seed * 6364136223846793005L + 1442695040888963407L;
return monad<M>::pure(std::make_pair(next, seed));
});
}
这表示从线性同余生成器获得输出。如果我们对 采取以下定义Id
:
template<typename A> using Id = A;
Id
'spure
只是返回传入的值,并且flatMap
只是将函数应用于该值。那么下面的定义应该是有效的:
StateT<Id, long, long> doubleXor = monad<PartiallyAppliedStateT<Id, long>::template Apply>::flatMap(nextLong<Id>(), [](long value1) {
return monad<PartiallyAppliedStateT<Id, long>::template Apply>::flatMap(nextLong<Id>(), [value1](long value2) {
return monad<PartiallyAppliedStateT<Id, long>::template Apply>::pure(value1 ^ value2);
});
});
该值doubleXor
表示将 LCG 的种子推进两次然后对两个输出进行异或的操作。但是编译器找不到我们上面具体定义的实例,只能找到没有定义方法monad
的默认实例:monad
In function 'long int doThing()':
error: 'flatMap' is not a member of 'monad<PartiallyAppliedStateT<Id, long int>::Apply>'
95 | StateT<Id, long, long> doubleXor = monad<PartiallyAppliedStateT<Id, long>::template Apply>::flatMap(nextLong<Id>(), [](long value1) {
| ^~~~~~~
In lambda function:
error: 'flatMap' is not a member of 'monad<PartiallyAppliedStateT<Id, long int>::Apply>'
96 | return monad<PartiallyAppliedStateT<Id, long>::template Apply>::flatMap(nextLong<Id>(), [value1](long value2) {
| ^~~~~~~
In lambda function:
error: 'pure' is not a member of 'monad<PartiallyAppliedStateT<Id, long int>::Apply>'
97 | return monad<PartiallyAppliedStateT<Id, long>::template Apply>::pure(value1 ^ value2);
| ^~~~
解决方案
推荐阅读
- python - TensorFlow 和 keras 得到相同的输出预测误差
- typescript - 如何在 TS 中实现接口并返回特定类型?
- python - 将DataFrame的每一列转换为字典,并根据列名命名字典
- xpages - 莲花笔记客户端中的客户端javascript不起作用
- regex - 如何在某个单词出现之前编写正则表达式来提取数字
- c - 从 N 行(从输入)获取字符并将它们作为十进制数存储在数组中
- powershell - PowerShell - 选择带小数点分隔符的数字 (DB2 SQL)
- c# - 从数据库中选择记录并显示相应行值的值
- c++ - 是否将 std::string 中的额外数据 memcopy 到 std::array
未定义的行为? - huawei-mobile-services - HMS Core Site Kit集成后使用textSearch接口报错码010010