fp
Functional Programming extensions to C++ for ROS projects.
monad.hpp
1 // Copyright (c) 2022, Tyler Weaver
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 //
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 //
13 // * Neither the name of the copyright holder nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 
29 #pragma once
30 
31 #include <optional>
32 
33 #include "fp/_external/expected.hpp"
34 
35 namespace fp {
36 
46 template <typename T>
47 constexpr std::optional<T> make_opt(T value) {
48  return std::optional<T>{value};
49 }
50 
62 template <typename T, typename F>
63 constexpr auto mbind(const std::optional<T>& opt, F f)
64  -> decltype(f(opt.value())) {
65  if (opt) {
66  return f(opt.value());
67  } else {
68  return {};
69  }
70 }
71 
85 template <typename T, typename E, typename F,
86  typename Ret = typename std::result_of<F(T)>::type>
87 constexpr Ret mbind(const tl::expected<T, E>& exp, F f) {
88  if (exp) {
89  return f(exp.value());
90  }
91  return tl::make_unexpected(exp.error());
92 }
93 
106 template <typename F, typename Ret = typename std::result_of<F()>::type,
107  typename Exp = tl::expected<Ret, std::exception_ptr>>
108 Exp mtry(F f) {
109  try {
110  return Exp{f()};
111  } catch (...) {
112  return tl::make_unexpected(std::current_exception());
113  }
114 }
115 
127 template <typename F, typename G>
128 constexpr auto mcompose(F f, G g) {
129  return [=](auto value) { return mbind(f(value), g); };
130 }
131 
145 template <typename T, typename G, typename... Types>
146 constexpr auto mcompose(T t, G g, Types... vars) {
147  auto exp = mcompose(t, g);
148  return mcompose(exp, vars...);
149 }
150 
151 } // namespace fp
152 
164 template <typename T, typename F>
165 constexpr auto operator|(const std::optional<T>& opt, F f) {
166  return fp::mbind(opt, f);
167 }
168 
182 template <typename T, typename E, typename F,
183  typename Ret = typename std::result_of<F(T)>::type>
184 constexpr Ret operator|(const tl::expected<T, E>& exp, F f) {
185  return fp::mbind(exp, f);
186 }
fp::make_opt
constexpr std::optional< T > make_opt(T value)
Makes an optional<T> from a T value.
Definition: monad.hpp:47
fp::mcompose
constexpr auto mcompose(F f, G g)
Monadic compose two monad functions.
Definition: monad.hpp:128
fp::mbind
constexpr auto mbind(const std::optional< T > &opt, F f) -> decltype(f(opt.value()))
Monad optional bind.
Definition: monad.hpp:63
fp
Definition: monad.hpp:35
fp::mtry
Exp mtry(F f)
Monadic try, used to lift a function that throws an exception one that returns an tl::expected<T,...
Definition: monad.hpp:108