Monad Toolkit
> Status: PATCH · 已对齐 PCR Master Blueprint v1.0 > 范畴: src/monad/{RWS.h, Free.h, Pipeline.h}、src/types/monad/ (legacy 位置,Wave 0 内迁出)
The "Haskell in C++" toolkit. This document defines the Monad templates, pipeline operators, and utility combinators that power the RWS and Free Monad implementations.
0. v1.0 命名 / 路径裁定
- 顶层命名空间
monad::(不是util::monad::) - 物理路径:
src/monad/{RWS.h, Free.h, Pipeline.h}(Wave 0 之前 v0 临时位置为src/types/monad/) - 不依赖任何业务子域(plant/fcc/...)
- Pipeline 别名定义在
simulation/pipeline/RWSTypes.h:cpp详见namespace sim { template <typename A> using WorldRWS = monad::RWS<WorldEnv, WorldState, WorldLog, A>; template <typename A> using BodyRWS = monad::RWS<BodyEnv, RocketBody, BodyLog, A>; }06_Simulation/Dual_Layer_RWS.md§2。
1. RWS Monad (Reader-Writer-State)
The core mechanism for both Dynamics and FCC computations.
R: Environment (Read-only config)S: State (Read-write context)W: Log (Append-only output, must be Monoid)A: Result type
> v1.0 模板参数顺序裁定:RWS<R, S, W, A>(State 在 Writer 之前)。理由:与 body_tick / world_tick 等动作的 .run(env, state) 顺序匹配。
// src/monad/RWS.h
namespace monad {
#include <functional>
#include <tuple>
#include <vector>
template <typename R, typename S, typename W, typename A>
class RWS {
public:
// The core computation: (R, S) -> (A, S, W)
using Computation = std::function<std::tuple<A, S, W>(const R&, S)>;
Computation run;
// --- Constructor ---
explicit RWS(Computation c) : run(std::move(c)) {}
// --- Core Operations ---
// Pure / Return
static RWS pure(A val) {
return RWS([val](const R&, S s) {
return std::make_tuple(val, s, W{});
});
}
// FlatMap / Bind (>>=)
template <typename B>
RWS<R, S, W, B> flatMap(std::function<RWS<R, S, W, B>(A)> f) const {
return RWS<R, S, W, B>([this, f](const R& r, S s) {
auto [a, s1, w1] = this->run(r, s);
auto [b, s2, w2] = f(a).run(r, s1);
return std::make_tuple(b, s2, w1 + w2); // Monoid accumulation
});
}
// Functor Map
template <typename B>
RWS<R, S, W, B> map(std::function<B(A)> f) const {
return flatMap<B>([f](A a) { return RWS<R, S, W, B>::pure(f(a)); });
}
};
// --- RWS Primitives ---
// Read Environment
template <typename R, typename S, typename W>
RWS<R, S, W, R> ask() {
return RWS<R, S, W, R>([](const R& r, S s) {
return std::make_tuple(r, s, W{});
});
}
// Get State
template <typename R, typename S, typename W>
RWS<R, S, W, S> get() {
return RWS<R, S, W, S>([](const R&, S s) {
return std::make_tuple(s, s, W{});
});
}
// Set State
template <typename R, typename S, typename W>
RWS<R, S, W, std::monostate> put(S new_state) {
return RWS<R, S, W, std::monostate>([new_state](const R&, S) {
return std::make_tuple(std::monostate{}, new_state, W{});
});
}
// Modify State
template <typename R, typename S, typename W>
RWS<R, S, W, std::monostate> modify(std::function<S(S)> f) {
return RWS<R, S, W, std::monostate>([f](const R&, S s) {
return std::make_tuple(std::monostate{}, f(s), W{});
});
}
// Write Log
template <typename R, typename S, typename W>
RWS<R, S, W, std::monostate> tell(W log) {
return RWS<R, S, W, std::monostate>([log](const R&, S s) {
return std::make_tuple(std::monostate{}, s, log);
});
}
} // namespace monad> Monoid 律要求:W 必须满足结合律 (a + b) + c == a + (b + c) 与单位元 W{}。详见 05_Dynamics_Core/Forces_Monoid.md §3 与 06_Simulation/Body_World_Tick.md §4。
2. Pipeline Operators
Syntactic sugar to eliminate callback hell.
Operator >>= (Bind)
Standard Haskell bind.
namespace monad {
template <typename R, typename S, typename W, typename A, typename F>
auto operator>>=(const RWS<R, S, W, A>& m, F&& f) {
return m.flatMap(std::forward<F>(f));
}
// Operator `|`: F# style pipe (alternative spelling)
template <typename R, typename S, typename W, typename A, typename F>
auto operator|(const RWS<R, S, W, A>& m, F&& f) {
return m.flatMap(std::forward<F>(f));
}
// Operator `>>`: discard left value
template <typename R, typename S, typename W, typename A, typename B>
auto operator>>(const RWS<R, S, W, A>& m, const RWS<R, S, W, B>& n) {
return m.template flatMap<B>([n](A) { return n; });
}
} // namespace monad3. Free Monad
For FCC algebraic descriptions(详见 04_FCC/Free_Monad_DSL.md):
// src/monad/Free.h
namespace monad {
template <typename F, typename A>
class Free {
// Pure A | Impure F<Free<F, A>>
std::variant<Pure<A>, Impure<F, A>> data_;
public:
static Free pure(A val);
template <typename B>
Free<F, B> flatMap(std::function<Free<F, B>(A)> f) const;
template <typename Interpreter>
auto fold(Interpreter& interp) const; // 用 interpreter 把 Free 翻译成具体 Monad
};
} // namespace monad详细应用见 04_FCC/Free_Monad_DSL.md 与 04_FCC/Interpreter_and_RWS.md。
4. Combinators
Utilities for composing Monadic actions.
namespace monad {
// Sequence: Run a list of actions in order
template <typename R, typename S, typename W, typename A>
RWS<R, S, W, std::vector<A>> sequence(const std::vector<RWS<R, S, W, A>>& actions);
// When: Run action if condition is true
template <typename R, typename S, typename W>
RWS<R, S, W, std::monostate> when(bool condition, RWS<R, S, W, std::monostate> action) {
if (condition) return action;
return RWS<R, S, W, std::monostate>::pure({});
}
} // namespace monad5. Usage Example: Body Physics Pipeline
using namespace monad;
using sim::BodyRWS;
auto plant_physics_stage =
ask<BodyEnv, RocketBody, BodyLog>()
>>= [](const BodyEnv& env) {
return get<BodyEnv, RocketBody, BodyLog>()
>>= [&env](RocketBody body) {
auto thrust = plant::compute_thrust_contribution(body.engine_effects);
auto drag = plant::compute_aero_contribution(body.dyn_in);
auto gravity = plant::compute_gravity_contribution();
return (thrust >> drag >> gravity); // Forces Monoid 累加
};
};详见 05_Dynamics_Core/Forces_Monoid.md §4 与 06_Simulation/Body_World_Tick.md §2.2 ③。
6. C-Distillation 路径
| C++ Monad | C 蜕化 |
|---|---|
RWS<R, S, W, A>::run(env, state) | 普通函数 int compute(const R*, S*, W*, A*),编译器内联 |
>>= / | / >> | 顺序 C 函数调用 |
Free<F, A> | switch-case 解释器(无 heap) |
std::function<...> Computation 包装 | 内联 lambda 或函数指针 |
std::tuple 返回 | 多 out-parameter 或 struct 返回 |
详见 08_Cross_Cutting/Implementation_Roadmap.md §7(C-Distillation Roadmap)。
7. 引用
- Blueprint §2.5(dynamics_core)、§2.6(simulation)、§3.1(FCC 三层架构)、§7.12(C-Distillation)
06_Simulation/Dual_Layer_RWS.md(WorldRWS / BodyRWS 别名)04_FCC/Free_Monad_DSL.md(Free Monad 用例)08_Cross_Cutting/Symmetric_RWS_Philosophy.md(设计哲学)