-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMaybe.h
81 lines (71 loc) · 2.25 KB
/
Maybe.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifndef SFL_MAYBE_H
#define SFL_MAYBE_H
#include <functional>
#include "sfl/sum.h"
#include "sfl/Prelude.h"
namespace sfl
{
class Nothing
{
};
template<typename A>
using Maybe = sum<Nothing, A>;
/*
* The maybe function takes a default value, a function, and a Maybe value. If the Maybe value is Nothing,
* the function returns the default value. Otherwise, it applies the function to the value inside and returns
* the result.
*/
template<typename MaybeType,typename A,typename M = typename MaybeType::type1,typename R = typename std::common_type<M,A>::type>
R maybe(const A &defaultValue, const MaybeType &m)
{
return match<M>(m, [&](const Nothing &){return defaultValue;},
[](const M &a){return a;});
}
/*
* The isNothing function returns True iff its argument is Nothing.
*/
template<typename MaybeType, typename M = typename MaybeType::type1>
bool isNothing(const MaybeType &m)
{
return match<bool>(m, [](const Nothing &){return true;},
[](const M &){return false;});
}
/*
* The isJust function returns True iff its argument has a vslue.
*/
template<typename MaybeType, typename M = typename MaybeType::type1>
bool isJust(const MaybeType &m)
{
return match<bool>(m, [](const Nothing &){return false;},
[](const M &){return true;});
}
/**
* Maps the f function over the Maybe, resulting in another Maybe which is just f(x) if m wasn't Nothing,
* otherwise Nothing.
*/
template<typename F, typename MaybeType, typename A = typename MaybeType::type1, typename B = typename std::result_of<F(A)>::type>
Maybe<B> fmap(F &&f, const MaybeType &m)
{
return match<Maybe<B>>(m, [](const Nothing &)->Maybe<B>{return Nothing();},
[&](const A &a)->Maybe<B>{return f(a);});
}
template<typename R, typename MaybeType = typename R::value_type, typename M = typename MaybeType::type1>
std::vector<M> catMaybes(const R &v)
{
std::vector<M> ret;
ret.reserve(length(v));
for (const auto &item : v) {
match<void>(item, [](const Nothing &){},
[&](const M &m){ret.push_back(m);});
}
return std::move(ret);
}
template<typename R,typename M = typename R::value_type>
Maybe<M> rangeToMaybe(const R &r)
{
return length(r) == 0
? Maybe<M>(Nothing())
: Maybe<M>(head(r));
}
}
#endif