fork(1) download
  1. #include <functional>
  2. #include <utility>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <iostream>
  6.  
  7. template<template<class ...> class M>
  8. struct Monad {
  9. // return :: a -> m a
  10. template<typename T>
  11. static auto ret(T a) -> M<T>;
  12.  
  13. // bind :: m a -> (a -> m b) -> m b
  14. template<typename T, typename U>
  15. static auto bind(M<T>, std::function<M<U>(T)>) -> M<U>;
  16. };
  17.  
  18. // return :: a -> m a
  19. template<template<class...> class M, typename T>
  20. auto ret(T a) -> M<T>
  21. {
  22. return Monad<M>::ret(std::move(a));
  23. }
  24.  
  25. // (>>=) :: m a -> (a -> m b) -> m b
  26. template<template<class...> class M, typename T, typename F>
  27. auto operator >>= (M<T> ma, F fun) -> decltype(fun(std::declval<T>())) // запутанно, но не знаю, как сделать лучше, чтобы работали лямбды
  28. {
  29. using R = decltype(fun(std::declval<T>()));
  30. return Monad<M>::bind(ma, std::function<R(T)>(std::move(fun)));
  31. }
  32.  
  33. // (>>) :: m a -> m b -> m b
  34. template<template<class...> class M, typename T, typename U>
  35. auto operator >> (M<T> ma, M<U> mb) -> M<U>
  36. {
  37. return ma >>= [=](T){ return mb; };
  38. }
  39.  
  40. template<typename T>
  41. struct list : private std::vector<T> {
  42. using impl = std::vector<T>;
  43. using impl::value_type;
  44.  
  45. list() = default;
  46. list(std::initializer_list<T> il)
  47. : std::vector<T>(std::move(il))
  48. {
  49. }
  50.  
  51. using impl::push_back;
  52. using impl::insert;
  53. using impl::begin;
  54. using impl::end;
  55. };
  56.  
  57. template<typename T>
  58. auto mk_list(std::initializer_list<T> il) -> list<T>
  59. {
  60. return list<T>(il);
  61. }
  62.  
  63. template<>
  64. template<typename T>
  65. auto Monad<list>::ret(T a) -> list<T>
  66. {
  67. // заворачиваем объект в список
  68. return list<T>{a};
  69. }
  70.  
  71. template<>
  72. template<typename T, typename U>
  73. auto Monad<list>::bind(list<T> ma, std::function<list<U>(T)> f) -> list<U>
  74. {
  75. // формируем список списков путем применения к каждому элементу переданной функции
  76. // (которая принимает объект, а возвращает монаду(список))
  77. list<list<U> > tmp;
  78. std::transform(ma.begin(), ma.end(), std::back_inserter(tmp), f);
  79.  
  80. // конкатенируем списки в один
  81. list<U> res;
  82. for (auto & v : tmp) {
  83. res.insert(res.end(), v.begin(), v.end());
  84. }
  85. return res;
  86. }
  87.  
  88. template<typename T, typename U>
  89. std::ostream & operator << (std::ostream & os, std::pair<T,U> p)
  90. {
  91. os << "(" << p.first << "," << p.second << ")";
  92. return os;
  93. }
  94.  
  95. template<typename T>
  96. std::ostream & operator << (std::ostream & os, const list<T> & a)
  97. {
  98. os << "[";
  99. int i = 0;
  100. for (auto & e : a) {
  101. if (i++) os << ",";
  102. os << e;
  103. }
  104. os << "]";
  105. return os;
  106. }
  107.  
  108. int main()
  109. {
  110. auto res = mk_list({1, 2, 3}) >>= [](auto x) {
  111. return mk_list({4, 5, 6}) >>= [=](auto y) {
  112. return ret<list>(std::make_pair(x, y));
  113. };
  114. };
  115. std::cout << res << std::endl;
  116. }
  117.  
Success #stdin #stdout 0s 3460KB
stdin
Standard input is empty
stdout
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]