c++ - 如何使 std::vector 在 Boost.Hana 中成为 Applicative 而不先使其成为 Monad?
问题描述
根据标题,我想了解如何制作但不是std::vector
(嗯,还没有)。这只是为了探索和理解Boost.Hana和函数式编程。Applicative
Monad
Functor
在hana/ext/std/vector.hpp
中,Functor
实例std::vector
被注释掉了,但是,如果我取消注释或将其复制到我的代码中,它似乎可以正常工作(编译器资源管理器)。
Applicative
但是,那里没有代码可以使它成为 a Applicative
(反过来,也没有使它成为 a Monad
),所以我已经研究了hana/concept/applicative.hpp
自己必须实现什么才能做到这一点。它需要和的_impl
表示。ap
lift
至于
lift
,以下是一个足够好的实现吗?template <> struct lift_impl<ext::std::vector_tag> { template <typename T> static std::vector<std::decay_t<T>> apply(T&& value) { return {std::forward<T>(value)}; } };
另一方面,由于
hana/lift.hpp
包含 s 的默认实现Sequence
,template <typename S> struct lift_impl<S, when<Sequence<S>::value>> { template <typename X> static constexpr decltype(auto) apply(X&& x) { return hana::make<S>(static_cast<X&&>(x)); } };
我也可以只做
std::vector
一个Sequence
,这更容易:template <> struct Sequence<ext::std::vector_tag> { static constexpr bool value = true; };
同样,
hana/ap.hpp
也有一个实现Sequences
,但它使用hana::chain
,因此它假定Monad
首先定义了一个实例。但是,如果我想制作
std::vector
aApplicative
而不是 aMonad
怎么办?我应该定制ap
自己。以下是正确的吗?template <> struct ap_impl<ext::std::vector_tag> { template<typename F, typename X, typename Y = std::decay_t<decltype((*std::declval<F>().begin())(*std::declval<X>().begin()))>> static constexpr std::vector<Y> apply(F&& f, X&& x) { std::vector<Y> result; result.reserve(f.size() * x.size()); for (auto const& f_ : f) { for (auto const& x_ : x) { result.emplace_back(f_(x_)); } } return result; } };
结果
乍一看,我认为它有效,因为在这个简单的情况下(编译器资源管理器)它确实给出了正确的结果:
int main()
{
auto vplus = std::vector{std::plus<int>{}};
auto vec = hana::ap(
std::vector{std::plus<int>{}}, // wrapping 1 object in a vector
std::vector<int>{10,20},
std::vector<int>{1,2});
BOOST_HANA_RUNTIME_ASSERT(vec == std::vector<int>{11,12,21,22});
}
失望
但是我在我的解决方案中看到了一些弱点:
- 我使用
std::vector
而不是lift
将 1 个函数包装到一个向量中,我相信这看起来有点不习惯; - 当我想到需要使用
std::vector
而不是的lift
情况时,即当我想应用多个函数时,我遇到了这样一个事实,例如,我不能将std::plus
andstd::minus
放在同一个向量中,因为它们是不同类型的函数对象。
对于hana::tuple
(或者std::tuple
如果我为它定义了所需的实例),这是小菜一碟,因为它可以容纳异构类型:
// TUPLE EXAMPLE
auto tuple = hana::ap(
hana::make_tuple(std::plus<int>{}, std::minus<>{}),
hana::make_tuple(10,20),
hana::make_tuple(1,2));
BOOST_HANA_RUNTIME_ASSERT(tuple == hana::make_tuple(11,12,21,22,9,8,19,18));
我的问题
有没有办法以适合的std::vector
方式Applicative
制作?// TUPLE EXAMPLE
std::vector
可能std::function
和/或类型擦除是完成任务所必需的?
解决方案
推荐阅读
- haskell - 基于数据构造函数的分区列表
- vb6 - Jenkins Pipeline:构建步骤不同时运行?
- python - 从 json 文件加载字符串
- c# - 菜鸟需要帮助以打破循环
- python - 如何使用 scikit-image 使用最近邻插值调整标记掩码的大小
- sql - SQL 选择 INTO 查询
- reactjs - 通过 GraphQL 和 Gatsby JS 从特定目录获取所有图像
- android - Android Espresso 的 HTML 报告和截图
- angular - 在Angular 2+中提交具有多个条件的表单
- shell - Applescript - 检查 URL 列表的页面内容是否包含 THIS_TEXT | 输出所有这些 URL