either_stream.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. #include <variant>
  10. template <typename T, typename E> using either = std::variant<T, E>;
  11. namespace stream {
  12. template <typename T> class either_stream;
  13. template <typename T> struct either_left;
  14. template <typename T, typename E> struct either_left<::either<T, E>> {
  15. using type = T;
  16. };
  17. template <typename T> using either_left_t = typename either_left<T>::type;
  18. template <typename T, typename E> class either_stream<::either<T, E>> {
  19. private:
  20. template <typename F, typename T2 = T>
  21. using map_f = decltype(std::declval<F>()(std::declval<T2>()));
  22. template <typename F, typename T2 = T>
  23. using flatmap_f = either_left_t<map_f<F, T2>>;
  24. private:
  25. ::either<T, E> value_;
  26. public:
  27. either_stream(E const & v) : value_(v) {}
  28. either_stream(E && v) : value_(std::forward<E>(v)) {}
  29. either_stream(T const & v) : value_(v) {}
  30. either_stream(T && v) : value_(std::forward<T>(v)) {}
  31. either_stream(::either<T, E> const & v) : value_(v) {}
  32. either_stream(::either<T, E> && v)
  33. : value_(std::forward<::either<T, E>>(v)) {}
  34. template <typename F>
  35. either_stream<::either<map_f<F>, E>> map(F && fun) const {
  36. using next_t = either_stream<::either<map_f<F>, E>>;
  37. return value_.index() == 0 ? next_t{fun(std::get<0>(value_))}
  38. : next_t{std::get<1>(value_)};
  39. }
  40. template <typename F>
  41. either_stream<::either<flatmap_f<F>, E>> flatmap(F && fun) const {
  42. using next_t = either_stream<::either<flatmap_f<F>, E>>;
  43. return value_.index() == 0 ? next_t{fun(std::get<0>(value_))}
  44. : next_t{std::get<1>(value_)};
  45. }
  46. template <typename FT, typename FE,
  47. typename = typename std::enable_if<
  48. !(std::is_void<map_f<FT>>::value &&
  49. std::is_void<map_f<FE, E>>::value)>::type>
  50. typename std::common_type<map_f<FT>, map_f<FE, E>>::type
  51. match(FT && left, FE && right) {
  52. return value_.index() == 0 ? left(std::get<0>(value_))
  53. : right(std::get<1>(value_));
  54. }
  55. template <typename FT, typename FE,
  56. typename = typename std::enable_if<
  57. std::is_void<map_f<FT>>::value &&
  58. std::is_void<map_f<FE, E>>::value>::type>
  59. void match(FT && left, FE && right) {
  60. value_.index() == 0 ? left(std::get<0>(value_))
  61. : right(std::get<1>(value_));
  62. }
  63. ::either<T, E> const & value() const { return value_; }
  64. };
  65. }
  66. namespace stream { namespace either {
  67. /**
  68. * Construct a stream from the given type while explicitly providing both the
  69. * type and the error class
  70. */
  71. template <typename T, typename E>
  72. auto make_stream(T const & opt) -> either_stream<::either<T, E>> {
  73. return {{opt}};
  74. }
  75. /**
  76. * Construct a stream from the given type where the real type is an inferred
  77. * property
  78. */
  79. template <typename E, typename T>
  80. auto make_stream(T const & opt) -> either_stream<::either<T, E>> {
  81. return {{opt}};
  82. }
  83. /**
  84. * Construct a stream with the given either-type as a template parameter.
  85. */
  86. template <typename E>
  87. auto make_stream(either_left_t<E> const & opt) -> either_stream<E> {
  88. return {{opt}};
  89. }
  90. }}