LeechCraft  0.6.70-15082-g543737046d
Modular cross-platform feature rich live environment.
monad.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include <optional>
12 #include "typelist.h"
13 #include "applicative.h"
14 #include "either.h"
15 
16 namespace LC
17 {
18 namespace Util
19 {
20  template<typename T>
21  struct InstanceMonad;
22 
23  template<template<typename...> class Monad, typename... Args, typename V>
24  auto Return (const V& v)
25  {
26  return Pure<Monad, Args...> (v);
27  }
28 
29  template<typename MV, typename F>
30  using BindResult_t = typename InstanceMonad<MV>::template BindResult_t<F>;
31 
32  namespace detail
33  {
34  template<template<typename...> class Monad, typename... Args1, typename... Args2>
35  constexpr bool IsCompatibleMonadImpl (const Monad<Args1...>*, const Monad<Args2...>*, int)
36  {
37  return std::is_same<
38  decltype (Init (Typelist<Args1...> {})),
39  decltype (Init (Typelist<Args2...> {}))
40  >::value;
41  }
42 
43  template<typename T1, typename T2>
44  constexpr bool IsCompatibleMonadImpl (const T1*, const T2*, ...)
45  {
46  return false;
47  }
48 
49  template<typename T>
50  constexpr T* declptr () noexcept
51  {
52  return nullptr;
53  }
54 
55  template<typename T1, typename T2>
56  constexpr bool IsCompatibleMonad ()
57  {
58  return IsCompatibleMonadImpl (detail::declptr<T1> (), detail::declptr<T2> (), 0);
59  }
60  }
61 
62  template<typename MV, typename F>
63  BindResult_t<MV, F> Bind (const MV& value, const F& f)
64  {
65  static_assert (detail::IsCompatibleMonad<MV, BindResult_t<MV, F>> (),
66  "Incompatible function return type");
67  return InstanceMonad<MV>::Bind (value, f);
68  }
69 
70  template<typename MV, typename F>
71  auto operator>> (const MV& value, const F& f) -> decltype (Bind (value, f))
72  {
73  return Bind (value, f);
74  }
75 
76  template<typename MV>
77  auto Do (const MV& value)
78  {
79  return value;
80  }
81 
82  template<typename MV, typename FHead, typename... FArgs>
83  auto Do (const MV& value, const FHead& fHead, const FArgs&... fArgs)
84  {
85  return Do (Bind (value, fHead), fArgs...);
86  }
87 
88  // Implementations
89  template<typename T>
90  struct InstanceMonad<std::optional<T>>
91  {
92  template<typename F>
93  using BindResult_t = std::result_of_t<F (T)>;
94 
95  template<typename F>
96  static BindResult_t<F> Bind (const std::optional<T>& value, const F& f)
97  {
98  if (!value)
99  return {};
100 
101  return f (*value);
102  }
103  };
104 
105  template<typename L, typename R>
106  struct InstanceMonad<Either<L, R>>
107  {
108  template<typename F>
109  using BindResult_t = std::result_of_t<F (R)>;
110 
111  template<typename F>
112  static BindResult_t<F> Bind (const Either<L, R>& value, const F& f)
113  {
114  using R_t = BindResult_t<F>;
115 
116  if (value.IsLeft ())
117  return R_t::Left (value.GetLeft ());
118 
119  return f (value.GetRight ());
120  }
121  };
122 }
123 }
typelist.h
LC::Util::Bind
BindResult_t< MV, F > Bind(const MV &value, const F &f)
Definition: monad.h:75
LC::Util::detail::IsCompatibleMonadImpl
constexpr bool IsCompatibleMonadImpl(const Monad< Args1... > *, const Monad< Args2... > *, int)
Definition: monad.h:47
LC::Util::InstanceMonad
Definition: monad.h:33
LC::Util::Pure
auto Pure(const T &v)
Definition: applicative.h:37
LC::Util::Either
Definition: either.h:33
LC::Util::Either::GetRight
const R & GetRight() const
Definition: either.h:85
LC::Util::operator>>
auto operator>>(const MV &value, const F &f) -> decltype(Bind(value, f))
Definition: monad.h:83
LC::Util::detail::declptr
constexpr T * declptr() noexcept
Definition: monad.h:62
LC::Util::Either::IsLeft
bool IsLeft() const
Definition: either.h:68
either.h
LC::Util::BindResult_t
typename InstanceMonad< MV >::template BindResult_t< F > BindResult_t
Definition: monad.h:42
LC::Util::Typelist
Definition: typelist.h:30
LC::Util::detail::IsCompatibleMonad
constexpr bool IsCompatibleMonad()
Definition: monad.h:68
LC::Util::Do
auto Do(const MV &value)
Definition: monad.h:89
LC::Util::Either::GetLeft
const L & GetLeft() const
Definition: either.h:78
applicative.h
LC
Definition: constants.h:14
LC::Util::oral::sph::f
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:952
LC::Util::InstanceMonad< std::optional< T > >::BindResult_t
std::result_of_t< F(T)> BindResult_t
Definition: monad.h:105
LC::Util::Return
auto Return(const V &v)
Definition: monad.h:36