mpc
Haskell-like feature supports in C++
state.hpp
Go to the documentation of this file.
1
2#pragma once
3#include <functional> // std::invoke
8#include <mpc/prelude/fst.hpp>
9
10// clang-format off
11
12namespace mpc {
13 // State
14 // [x] State
15 // [x] is_State
16 // [x] State_state_t
17 // [x] State_monad_t
18 // [x] make_State
19 // [x] run_State
20
22 template <class S, is_Identity M>
24
25 // is_State
26 namespace detail {
27 template <class>
28 struct is_State_impl : std::false_type {};
29
30 template <class S, is_Identity M>
31 struct is_State_impl<StateT<S, M>> : std::true_type {};
32 } // namespace detail
33
34 template <class T>
35 concept is_State = detail::is_State_impl<std::remove_cvref_t<T>>::value;
36
37 template <is_State ST>
38 using State_state_t = StateT_state_t<ST>;
39
40 template<is_State ST>
41 using State_monad_t = StateT_monad_t<ST>;
42
43 // make_State, run_State
44 namespace detail {
45 template <class S>
47 using state_type = std::decay_t<S>;
48
49 template <class Fn>
50 requires std::invocable<Fn&, state_type> and is_Identity<std::invoke_result_t<Fn&, state_type>>
51 constexpr auto operator()(Fn&& f) const {
52 using M = std::invoke_result_t<Fn&, state_type>;
53 return State<state_type, M>(std::forward<Fn>(f));
54 }
55 };
56
57 struct run_State_op {
58 template <is_State ST>
59 constexpr auto operator()(ST&& x) const noexcept
60 -> decltype(compose(run_Identity, run_StateT % std::forward<ST>(x))) {
61 return compose(run_Identity, run_StateT % std::forward<ST>(x));
62 }
63 };
64 } // namespace detail
65
66 inline namespace cpo {
67 template <class S>
68 inline constexpr partial<detail::make_State_op<S>> make_State{};
69
70 inline constexpr partial<detail::run_State_op> run_State{};
71 } // namespace cpo
72
73 // Grobal methods:
74 // [x] eval_State
75 // [x] exec_State
76 // [x] map_State
77 // [x] with_State
78
79 // eval_State, exec_State, map_State, with_State
80 namespace detail {
81 // clang-format off
83 template <is_State ST, class T>
84 constexpr auto operator()(ST&& x, T&& t) const noexcept(
85 noexcept( fst(run_State % std::forward<ST>(x) % std::forward<T>(t))))
86 -> decltype(fst(run_State % std::forward<ST>(x) % std::forward<T>(t))) {
87 return fst(run_State % std::forward<ST>(x) % std::forward<T>(t));
88 }
89 };
90
92 template <is_State ST, class T>
93 constexpr auto operator()(ST&& x, T&& t) const noexcept(
94 noexcept( snd(run_State % std::forward<ST>(x) % std::forward<T>(t))))
95 -> decltype(snd(run_State % std::forward<ST>(x) % std::forward<T>(t))) {
96 return snd(run_State % std::forward<ST>(x) % std::forward<T>(t));
97 }
98 };
99
101 template <class Fn2, is_State ST>
102 constexpr auto operator()(Fn2&& f, ST&& x) const noexcept(
103 noexcept( map_StateT % compose(make_Identity, compose(std::forward<Fn2>(f), run_Identity)) % std::forward<ST>(x)))
104 -> decltype(map_StateT % compose(make_Identity, compose(std::forward<Fn2>(f), run_Identity)) % std::forward<ST>(x)) {
105 return map_StateT % compose(make_Identity, compose(std::forward<Fn2>(f), run_Identity)) % std::forward<ST>(x);
106 }
107 };
108 // clang-format on
109 } // namespace detail
110
111 inline namespace cpo {
112 inline constexpr partial<detail::eval_State_op> eval_State{};
113
114 inline constexpr partial<detail::exec_State_op> exec_State{};
115
116 inline constexpr partial<detail::map_State_op> map_State{};
117
118 inline constexpr auto with_State = with_StateT;
119 } // namespace cpo
120} // namespace mpc
121
122// clang-format on
constexpr partial< detail::_fst::get_op< 1 > > snd
Returns the second element of the given tuple-like object.
Definition: fst.hpp:34
constexpr partial< detail::compose_op > compose
Function composition.
Definition: compose.hpp:35
constexpr partial< detail::_fst::get_op< 0 > > fst
Returns the first element of the given tuple-like object.
Definition: fst.hpp:29
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
Definition: stateT.hpp:29
Definition: state.hpp:82
Definition: state.hpp:91
Definition: state.hpp:28
Definition: state.hpp:46
Definition: state.hpp:100
Definition: state.hpp:57
Implements a perfect-forwarding call wrapper.
Definition: partial.hpp:63