mpc
Haskell-like feature supports in C++
monad.hpp
Go to the documentation of this file.
1
2#pragma once
3#include <functional> // std::invoke
6
7// clang-format off
8
9namespace mpc {
10 // monad
11 // https://hackage.haskell.org/package/base-4.16.0.0/docs/Control-Monad.html#t:Monad
12
14 template <class>
16
18 template <class M>
19 concept monad_traits_specialized = requires {
20 monad_traits<std::remove_cvref_t<M>>::bind;
21 };
22
24 template <class M>
26
27 // Methods required for the class definition.
28
29 namespace detail {
34 struct bind_op {
35 template <class Ma, class Fn>
36 constexpr auto operator()(Ma&& ma, Fn&& fn) const noexcept(
37 noexcept( monad_traits<std::remove_cvref_t<Ma>>::bind(std::forward<Ma>(ma), std::forward<Fn>(fn))))
38 -> decltype(monad_traits<std::remove_cvref_t<Ma>>::bind(std::forward<Ma>(ma), std::forward<Fn>(fn)))
39 { return monad_traits<std::remove_cvref_t<Ma>>::bind(std::forward<Ma>(ma), std::forward<Fn>(fn)); }
40 };
41 } // namespace detail
42
43 inline namespace cpo {
45 inline constexpr partial<detail::bind_op> bind{};
46 } // namespace cpo
47
49 namespace monads {
50 namespace detail {
57 struct fmap_op {
58 template <class Fn, class Ma>
59 constexpr auto operator()(Fn&& fn, Ma&& ma) const noexcept(
60 noexcept( mpc::bind(std::forward<Ma>(ma), compose(mpc::pure<Ma>, std::forward<Fn>(fn)))))
61 -> decltype(mpc::bind(std::forward<Ma>(ma), compose(mpc::pure<Ma>, std::forward<Fn>(fn))))
62 { return mpc::bind(std::forward<Ma>(ma), compose(mpc::pure<Ma>, std::forward<Fn>(fn))); }
63 };
64
71 struct seq_apply_op {
72 struct closure {
73 template<class Ma, class Fn>
74 constexpr auto operator()(Ma&& ma, Fn&& fn) const noexcept(
75 noexcept( mpc::bind(std::forward<Ma>(ma), compose(mpc::pure<Ma>, std::forward<Fn>(fn)))))
76 -> decltype(mpc::bind(std::forward<Ma>(ma), compose(mpc::pure<Ma>, std::forward<Fn>(fn))))
77 { return mpc::bind(std::forward<Ma>(ma), compose(mpc::pure<Ma>, std::forward<Fn>(fn))); }
78 };
79
80 template<class Mab, class Ma>
81 constexpr auto operator()(Mab&& mab, Ma&& ma) const noexcept(
82 noexcept( mpc::bind(std::forward<Mab>(mab), partial(closure{}, std::forward<Ma>(ma)))))
83 -> decltype(mpc::bind(std::forward<Mab>(mab), partial(closure{}, std::forward<Ma>(ma))))
84 { return mpc::bind(std::forward<Mab>(mab), partial(closure{}, std::forward<Ma>(ma))); }
85 };
86
94 template<class Ma, class Mb>
95 constexpr auto operator()(Ma&& ma, Mb&& mb) const noexcept(
96 noexcept( mpc::bind(std::forward<Ma>(ma), constant % std::forward<Mb>(mb))))
97 -> decltype(mpc::bind(std::forward<Ma>(ma), constant % std::forward<Mb>(mb)))
98 { return mpc::bind(std::forward<Ma>(ma), constant % std::forward<Mb>(mb)); }
99 };
100 } // namespace detail
101
103 inline constexpr partial<detail::fmap_op> fmap{};
104
107
110 } // namespace monads
111
112 // Grobal methods
113
114 namespace detail {
122 struct karrow_op {
123 template <class Fn, class Gn, class A>
124 constexpr auto operator()(Fn&& fn, Gn&& gn, A&& a) const noexcept(
125 noexcept( mpc::bind(std::invoke(std::forward<Fn>(fn), std::forward<A>(a)), std::forward<Gn>(gn))))
126 -> decltype(mpc::bind(std::invoke(std::forward<Fn>(fn), std::forward<A>(a)), std::forward<Gn>(gn)))
127 { return mpc::bind(std::invoke(std::forward<Fn>(fn), std::forward<A>(a)), std::forward<Gn>(gn)); }
128 };
129 } // namespace detail
130
131 inline namespace cpo {
139 template <class M>
140 requires requires {
142 }
143 inline constexpr auto returns = mpc::pure<M>;
144
147 } // namespace cpo
148} // namespace mpc
149
150// clang-format on
Requires functor and pure, seq_apply, liftA2, discard2nd and discard1st is valid in applicative_trait...
Definition: applicative.hpp:32
monad_traits_specialized
Definition: monad.hpp:19
Requires applicative and bind is valid in monad_traits .
Definition: monad.hpp:25
constexpr partial< detail::bind_op > bind
bind :: forall a b. m a -> (a -> m b) -> m b
Definition: monad.hpp:45
constexpr partial< detail::constant_op > constant
Returns a unary function always returning the first input.
Definition: constant.hpp:21
constexpr partial< detail::compose_op > compose
Function composition.
Definition: compose.hpp:35
constexpr partial< detail::karrow_op > karrow
karrow :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
Definition: monad.hpp:146
constexpr auto returns
returns :: a -> m a
Definition: monad.hpp:143
constexpr partial< detail::pure_op< F > > pure
pure :: a -> f a
Definition: applicative.hpp:96
constexpr partial< detail::discard1st_op > discard1st
discard1st :: f a -> f b -> f b
Definition: monad.hpp:109
constexpr partial< detail::seq_apply_op > seq_apply
seq_apply :: f (a -> b) -> f a -> f b
Definition: monad.hpp:106
constexpr partial< detail::fmap_op > fmap
fmap :: (a -> b) -> f a -> f b
Definition: monad.hpp:103
class Functor f => Applicative f where
Definition: applicative.hpp:18
bind :: forall a b. m a -> (a -> m b) -> m b
Definition: monad.hpp:34
karrow :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
Definition: monad.hpp:122
class Applicative m => Monad m where
Definition: monad.hpp:15
discard1st :: f a -> f b -> f b
Definition: monad.hpp:93
fmap :: (a -> b) -> f a -> f b
Definition: monad.hpp:57
seq_apply :: f (a -> b) -> f a -> f b
Definition: monad.hpp:71
Implements a perfect-forwarding call wrapper.
Definition: partial.hpp:63