either_stream.hpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //
  2. // either_stream.hpp
  3. // optional.stream
  4. //
  5. // Created by Sam Jaffe on 1/28/17.
  6. //
  7. #pragma once
  8. #include <type_traits>
  9. #if __cplusplus > 201402L
  10. #include <variant>
  11. template <typename T, typename E>
  12. using either = std::variant<T, E>;
  13. #else
  14. #include "variant/variant.hpp"
  15. template <typename T, typename E>
  16. using either = variant<T, E>;
  17. #endif
  18. namespace stream { namespace either {
  19. namespace detail {
  20. template <typename T> class either_stream;
  21. template <typename T> struct either_left;
  22. template <typename T, typename E>
  23. struct either_left<::either<T, E>> { using type = T; };
  24. template <typename T, typename E>
  25. class either_stream<::either<T, E>> {
  26. private:
  27. template <typename F, typename T2>
  28. using map_f = decltype(std::declval<F>()(std::declval<T2>()));
  29. template <typename F, typename T2>
  30. using flatmap_f = typename either_left<decltype(std::declval<F>()(std::declval<T2>()))>::type;
  31. public:
  32. either_stream(E const & v) : value(v) {}
  33. either_stream(E && v) : value(std::forward<E>(v)) {}
  34. either_stream(T const & v) : value(v) {}
  35. either_stream(T && v) : value(std::forward<T>(v)) {}
  36. either_stream(::either<T, E> const & v) : value(v) {}
  37. either_stream(::either<T, E> && v) : value(std::forward<::either<T, E>>(v)) {}
  38. template <typename F>
  39. either_stream<::either<map_f<F, T>, E>> map(F && fun) const {
  40. using next_t = either_stream<::either<map_f<F, T>, E>>;
  41. return value.index() == 0 ? next_t{fun(std::get<0>(value))} : next_t{std::get<1>(value)};
  42. }
  43. template <typename F>
  44. either_stream<::either<flatmap_f<F, T>, E>> flatmap(F && fun) const {
  45. using next_t = either_stream<::either<flatmap_f<F, T>, E>>;
  46. return value.index() == 0 ? next_t{fun(std::get<0>(value))} : next_t{std::get<1>(value)};
  47. }
  48. template <typename FT, typename FE, typename = typename std::enable_if<!(std::is_void<map_f<FT, T>>::value && std::is_void<map_f<FE, E>>::value)>::type>
  49. typename std::common_type<map_f<FT, T>, map_f<FE, E>>::type match(FT && left, FE && right) {
  50. return value.index() == 0 ? left(std::get<0>(value)) : right(std::get<1>(value));
  51. }
  52. template <typename FT, typename FE, typename = typename std::enable_if<std::is_void<map_f<FT, T>>::value && std::is_void<map_f<FE, E>>::value>::type>
  53. void match(FT && left, FE && right) {
  54. value.index() == 0 ? left(std::get<0>(value)) : right(std::get<1>(value));
  55. }
  56. private:
  57. ::either<T, E> value;
  58. };
  59. }
  60. template <typename T, typename E>
  61. auto make_stream(T const & opt) -> detail::either_stream<::either<T, E>> {
  62. return {{opt}};
  63. }
  64. template <typename E, typename T>
  65. auto make_stream(T const & opt) -> detail::either_stream<::either<T, E>> {
  66. return {{opt}};
  67. }
  68. template <typename E>
  69. auto make_stream(typename detail::either_left<E>::type const & opt) -> detail::either_stream<E> {
  70. return {{opt}};
  71. }
  72. } }