fork(1) download
  1. #include <functional>
  2. #include <utility>
  3.  
  4. template<template<class ...> class M>
  5. struct Monad {
  6. // return :: a -> m a
  7. template<typename T>
  8. static auto ret(T a) -> M<T>;
  9.  
  10. // bind :: m a -> (a -> m b) -> m b
  11. template<typename T, typename U>
  12. static auto bind(M<T>, std::function<M<U>(T)>) -> M<U>;
  13. };
  14.  
  15. // return :: a -> m a
  16. template<template<class...> class M, typename T>
  17. auto ret(T a) -> M<T>
  18. {
  19. return Monad<M>::ret(std::move(a));
  20. }
  21.  
  22. // (>>=) :: m a -> (a -> m b) -> m b
  23. template<template<class...> class M, typename T, typename F>
  24. auto operator >>= (M<T> ma, F fun) -> decltype(fun(std::declval<T>())) // запутанно, но не знаю, как сделать лучше, чтобы работали лямбды
  25. {
  26. using R = decltype(fun(std::declval<T>()));
  27. return Monad<M>::bind(ma, std::function<R(T)>(std::move(fun)));
  28. }
  29.  
  30. // (>>) :: m a -> m b -> m b
  31. template<template<class...> class M, typename T, typename U>
  32. auto operator >> (M<T> ma, M<U> mb) -> M<U>
  33. {
  34. return ma >>= [=](T){ return mb; };
  35. }
  36.  
  37.  
  38. template<typename T>
  39. struct value { // просто коробка со значением
  40. value(T a)
  41. : x(a)
  42. {}
  43.  
  44. T x;
  45. };
  46.  
  47. // специализируем ret
  48. template<>
  49. template<typename T>
  50. auto Monad<value>::ret(T a) -> value<T>
  51. {
  52. return value<T>(a);
  53. }
  54.  
  55. // специализируем bind
  56. template<>
  57. template<typename T, typename U>
  58. auto Monad<value>::bind(value<T> d, std::function<value<U>(T)> f) -> value<U>
  59. {
  60. return f(d.x);
  61. }
  62.  
  63. #include <iostream>
  64.  
  65. auto succ(int x) -> value<int>
  66. {
  67. return ret<value>(x + 1);
  68. }
  69.  
  70. int main()
  71. {
  72. auto v = (ret<value>(10) >>= succ) >>= succ;
  73.  
  74. std::cout << v.x << std::endl;
  75. }
  76.  
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
12