Created
August 30, 2019 11:50
-
-
Save laparca/35c7065e0f9d4256a611ec5d6568e3c2 to your computer and use it in GitHub Desktop.
Simple monad concept in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
namespace lzcoders { | |
namespace MonadHelpers { | |
template<typename T> struct value_type { using type = typename std::decay<T>::type::value_type; }; | |
template<typename T> using ValueType = typename value_type<T>::type; | |
struct dummy { | |
dummy(const dummy&) = default; | |
dummy(dummy&&) = default; | |
dummy() = default; | |
}; | |
template<class T, class X> struct rebind; | |
template<class T, class X> using rebind_t = typename rebind<T, X>::type; | |
template<template<class...> class T, class X, class Y, class... Z> struct rebind<T<X, Z...>, Y> { | |
using type = T<Y, Z...>; | |
}; | |
template<typename M> using dummy_function = std::function<rebind_t<M, dummy>(ValueType<M> const&)>; | |
template<typename... Monad> | |
struct monad_t; | |
} | |
template<typename M> | |
concept bool Monad = requires (M m) { | |
typename MonadHelpers::ValueType<M>; | |
typename MonadHelpers::monad_t<M>; | |
{ MonadHelpers::monad_t<M>::wrap(MonadHelpers::ValueType<M>{}) } -> M; | |
{ MonadHelpers::monad_t<M>::apply(m, MonadHelpers::dummy_function<M>{}) } -> MonadHelpers::rebind_t<M, MonadHelpers::dummy>; | |
}; | |
template<template<typename...>typename M, typename T, typename... Ts> requires Monad<M<T, Ts...>> | |
auto mwrap(T&& t) { | |
return MonadHelpers::monad_t<M<T, Ts...>>::wrap(std::forward<T>(t)); | |
} | |
template<typename M, typename F> requires Monad<M> | |
auto mapply(M&& m, F&& f) { | |
return MonadHelpers::monad_t<M>::apply(std::forward<M>(m), std::forward<F>(f)); | |
} | |
template<typename M, typename F> requires Monad<M> | |
auto operator>>(M&& m, F&& f) { | |
return mapply(std::forward<M>(m), std::forward<F>(f)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment