forked from AndreyTsvetkov/Functional.Maybe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MaybeCompositions.cs
119 lines (110 loc) · 3.41 KB
/
MaybeCompositions.cs
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Collections.Generic;
// ReSharper disable MemberCanBePrivate.Global
namespace Functional.Maybe
{
/// <summary>
/// Composing two maybe value to one, such operations, as one.Or(another)
/// </summary>
public static class MaybeCompositions
{
/// <summary>
/// Returns <paramref name="a"/> if its Value exists or returns <paramref name="b"/>, wrapped as Maybe
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Maybe<T> Or<T>(this Maybe<T> a, T b)
{
if (a.IsSomething())
return a;
return b.ToMaybe();
}
/// <summary>
/// Returns <paramref name="a"/> if its Value exists or returns <paramref name="b"/>()
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Maybe<T> Or<T>(this Maybe<T> a, Func<Maybe<T>> b)
{
if (a.IsSomething())
return a;
return b();
}
/// <summary>
/// Returns <paramref name="a"/> if its Value exists or returns <paramref name="b"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Maybe<T> Or<T>(this Maybe<T> a, Maybe<T> b)
{
if (a.IsSomething())
return a;
return b;
}
/// <summary>
/// Returns <paramref name="b"/> if <paramref name="a"/> has value, otherwise <see cref="Maybe<T>.Nothing"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Maybe<T2> Compose<T, T2>(this Maybe<T> a, Maybe<T2> b)
{
if (a.IsNothing())
return Maybe<T2>.Nothing;
return b;
}
/// <summary>
/// Collapses nested maybes to a flat one
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static Maybe<T> Collapse<T>(this Maybe<Maybe<T>> t)
{
// using implicit cast
return t;
}
/// <summary>
/// Flattens a recursive Maybe structure into IEnumerable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="maybe"></param>
/// <param name="parentSelector"></param>
/// <example>
/// Having { a: 1, parent: { a: 2, parent: { a: 3, parent: Nothing } } }
/// We can flatten it to
/// [
/// { a: 1, parent: { a: 2, parent: { a: 3, parent: Nothing } } },
/// { a: 2, parent: { a: 3, parent: Nothing } } ,
/// { a: 3, parent: Nothing }
/// ]
/// </example>
/// <returns></returns>
public static IEnumerable<T> Flatten<T>(this Maybe<T> maybe, Func<T, Maybe<T>> parentSelector)
{
return maybe.FlattenSelect(parentSelector, x => x);
}
private static IEnumerable<TFlatten> FlattenSelect<TMaybe, TFlatten>(this Maybe<TMaybe> maybe, Func<TMaybe, Maybe<TMaybe>> parentSelector, Func<TMaybe, TFlatten> flattenSelector)
{
return maybe.Flatten(parentSelector, new List<TFlatten>(), flattenSelector);
}
private static IEnumerable<TFlatten> Flatten<TMaybe, TFlatten>(this Maybe<TMaybe> maybe, Func<TMaybe, Maybe<TMaybe>> parentSelector, List<TFlatten> acc, Func<TMaybe, TFlatten> flattenSelector)
{
while (true)
{
if (maybe.IsNothing())
return acc;
acc.Add(flattenSelector(maybe.Value));
maybe = parentSelector(maybe.Value);
}
}
}
}