LeechCraft 0.6.70-14794-g33744ae6ce
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
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
16namespace LC
17{
18namespace Util
19{
20 template<typename T>
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>
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}
const L & GetLeft() const
Definition: either.h:60
bool IsLeft() const
Definition: either.h:50
const R & GetRight() const
Definition: either.h:67
constexpr T * declptr() noexcept
Definition: monad.h:50
constexpr bool IsCompatibleMonad()
Definition: monad.h:56
constexpr bool IsCompatibleMonadImpl(const Monad< Args1... > *, const Monad< Args2... > *, int)
Definition: monad.h:35
constexpr auto Init(List< Args... >)
Definition: typelist.h:89
auto Do(const MV &value)
Definition: monad.h:77
auto operator>>(const MV &value, const F &f) -> decltype(Bind(value, f))
Definition: monad.h:71
auto Return(const V &v)
Definition: monad.h:24
typename InstanceMonad< MV >::template BindResult_t< F > BindResult_t
Definition: monad.h:30
BindResult_t< MV, F > Bind(const MV &value, const F &f)
Definition: monad.h:63
auto Pure(const T &v)
Definition: applicative.h:25
Definition: constants.h:15
STL namespace.
static BindResult_t< F > Bind(const Either< L, R > &value, const F &f)
Definition: monad.h:112
std::result_of_t< F(R)> BindResult_t
Definition: monad.h:109
std::result_of_t< F(T)> BindResult_t
Definition: monad.h:93
static BindResult_t< F > Bind(const std::optional< T > &value, const F &f)
Definition: monad.h:96