mpc
Haskell-like feature supports in C++
class.hpp
Go to the documentation of this file.
1
2#pragma once
5
6// clang-format off
7
8namespace mpc {
9 // monad_state
10 // https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Class.html
11
12 template <class>
14
15 template <class ST>
16 concept monad_state = requires {
20 };
21
22 // Methods required for the class definition.
23
24 namespace detail {
26 template <class ST>
27 struct state_op {
28 template <class Fn>
29 constexpr auto operator()(Fn&& fn) const noexcept(
30 noexcept( monad_state_traits<std::remove_cvref_t<ST>>::state(std::forward<Fn>(fn))))
31 -> decltype(monad_state_traits<std::remove_cvref_t<ST>>::state(std::forward<Fn>(fn)))
32 { return monad_state_traits<std::remove_cvref_t<ST>>::state(std::forward<Fn>(fn)); }
33 };
34
39 template <class ST>
40 struct gets_op {
41 constexpr auto operator*() const noexcept(
45 };
46
48 template <class ST>
49 struct put_op {
50 template <class S>
51 constexpr auto operator()(S&& s) const noexcept(
52 noexcept( monad_state_traits<std::remove_cvref_t<ST>>::put(std::forward<S>(s))))
53 -> decltype(monad_state_traits<std::remove_cvref_t<ST>>::put(std::forward<S>(s)))
54 { return monad_state_traits<std::remove_cvref_t<ST>>::put(std::forward<S>(s)); }
55 };
56 } // namespace detail
57
58 inline namespace cpo {
60 template <class ST>
62
64 template <class ST>
65 inline constexpr detail::gets_op<ST> gets{};
66
68 template <class ST>
69 inline constexpr partial<detail::put_op<ST>> put{};
70 } // namespace cpo
71
72 // Deducibles
73 // [ ] state
74 // [x] gets
75 // [x] put
76
77 namespace states {
78 namespace detail {
85
88 template <class ST>
89 struct gets_op {
90 struct closure {
91 template <class T>
92 constexpr auto operator()(T&& t) const noexcept(
93 noexcept( std::make_pair(t, t)))
94 -> decltype(std::make_pair(t, t)) {
95 auto t2 = t;
96 return std::make_pair(std::forward<T>(t), std::move(t2));
97 }
98 };
99
100 constexpr auto operator()() const noexcept(
101 noexcept( mpc::state<ST>(closure{})))
102 -> decltype(mpc::state<ST>(closure{})) {
103 return mpc::state<ST>(closure{});
104 }
105 };
106
109 template <class ST>
110 struct put_op {
111 struct closure {
112 template <class T, class A>
113 constexpr auto operator()(T&& t, A&&) const noexcept(
114 noexcept( std::make_pair(unit, std::forward<T>(t))))
115 -> decltype(std::make_pair(unit, std::forward<T>(t))) {
116 return std::make_pair(unit, std::forward<T>(t));
117 }
118 };
119
120 template <class T>
121 constexpr auto operator()(T&& t) const noexcept(
122 noexcept( mpc::state<ST>(partial(closure{}, std::forward<T>(t)))))
123 -> decltype(mpc::state<ST>(partial(closure{}, std::forward<T>(t)))) {
124 return mpc::state<ST>(partial(closure{}, std::forward<T>(t)));
125 }
126 };
127 } // namespace detail
128
129 // /// state :: (s -> (a, s)) -> m a
130 // template <class ST>
131 // inline constexpr partial<detail::state_op<ST>> state{};
132
134 template <class ST>
135 requires requires {
136 monad_state_traits<std::remove_cvref_t<ST>>::state;
137 }
138 inline constexpr detail::gets_op<ST> gets{};
139
141 template <class ST>
142 requires requires {
144 }
145 inline constexpr partial<detail::put_op<ST>> put{};
146 } // namespace states
147
148 // Grobal methods
149 // [x] modify
150 // [ ] modify'
151 // [x] getss
152
153 // modify, getss
154 namespace detail {
156 template <class ST>
157 struct modify_op {
158 struct closure {
159 template <class Fn, class T>
160 constexpr auto operator()(Fn&& f, T&& t) const noexcept(
161 noexcept( std::make_pair(unit, std::invoke(std::forward<Fn>(f), std::forward<T>(t)))))
162 -> decltype(std::make_pair(unit, std::invoke(std::forward<Fn>(f), std::forward<T>(t)))) {
163 return std::make_pair(unit, std::invoke(std::forward<Fn>(f), std::forward<T>(t)));
164 }
165 };
166
167 template <class Fn>
168 constexpr auto operator()(Fn&& f) const noexcept(
169 noexcept( mpc::state<ST>(partial(closure{}, std::forward<Fn>(f)))))
170 -> decltype(mpc::state<ST>(partial(closure{}, std::forward<Fn>(f)))) {
171 return mpc::state<ST>(partial(closure{}, std::forward<Fn>(f)));
172 }
173 };
174
176 template <class ST>
177 struct getss_op {
178 struct closure {
179 template <class Fn, class T>
180 constexpr auto operator()(Fn&& f, T&& t) const noexcept(
181 noexcept( std::make_pair(std::invoke(std::forward<Fn>(f), t), t)))
182 -> decltype(std::make_pair(std::invoke(std::forward<Fn>(f), t), t)) {
183 auto t2 = t;
184 return std::make_pair(std::invoke(std::forward<Fn>(f), std::forward<T>(t)), std::move(t2));
185 }
186 };
187
188 template <class Fn>
189 constexpr auto operator()(Fn&& f) const noexcept(
190 noexcept( mpc::state<ST>(partial(closure{}, std::forward<Fn>(f)))))
191 -> decltype(mpc::state<ST>(partial(closure{}, std::forward<Fn>(f)))) {
192 return mpc::state<ST>(partial(closure{}, std::forward<Fn>(f)));
193 }
194 };
195 } // namespace detail
196
197 inline namespace cpo {
199 template <class ST>
201
203 template <class ST>
205 } // namespace cpo
206}
207
208// clang-format on
constexpr partial< detail::modify_op< std::remove_cvref_t< ST > > > modify
modify :: MonadState s m => (s -> s) -> m ()
Definition: class.hpp:200
constexpr partial< detail::getss_op< std::remove_cvref_t< ST > > > getss
getss :: MonadState s m => (s -> a) -> m a
Definition: class.hpp:204
constexpr partial< detail::put_op< ST > > put
put :: s -> m ()
Definition: class.hpp:69
constexpr detail::gets_op< ST > gets
gets :: m s
Definition: class.hpp:65
constexpr partial< detail::state_op< ST > > state
state :: (s -> (a, s)) -> m a
Definition: class.hpp:61
gets :: m s
Definition: class.hpp:40
Definition: class.hpp:178
getss :: MonadState s m => (s -> a) -> m a
Definition: class.hpp:177
Definition: class.hpp:158
modify :: MonadState s m => (s -> s) -> m ()
Definition: class.hpp:157
put :: s -> m ()
Definition: class.hpp:49
state :: (s -> (a, s)) -> m a
Definition: class.hpp:27
Definition: class.hpp:13
Implements a perfect-forwarding call wrapper.
Definition: partial.hpp:63
Definition: class.hpp:89
Definition: class.hpp:111
Definition: class.hpp:110
constexpr unit_t unit
An entity of an empty tuple.
Definition: unit.hpp:10