BadScript 2
Loading...
Searching...
No Matches
Either.cs
Go to the documentation of this file.
1//#define CSX_EITHER_INTERNAL // Uncomment or define at build time to set accessibility to internal.
2//#define CSX_REM_MAYBE_FUNC // Uncomment or define at build time to remove dependency to Maybe.cs.
3
4using System;
5
6namespace CSharpx
7{
8#region Either Type
9
10#if !CSX_EITHER_INTERNAL
11 public
12#endif
13 internal enum EitherType
14 {
18 Left,
19
23 Right,
24 }
25
26#if !CSX_EITHER_INTERNAL
27 public
28#endif
29 internal abstract class Either<TLeft, TRight>
30 {
31 protected Either(EitherType tag)
32 {
33 Tag = tag;
34 }
35
36 public EitherType Tag { get; }
37
38#region Basic Match Methods
39
40 public bool MatchLeft(out TLeft value)
41 {
42 value = Tag == EitherType.Left ? ((Left<TLeft, TRight>)this).Value : default;
43
44 return Tag == EitherType.Left;
45 }
46
47 public bool MatchRight(out TRight value)
48 {
49 value = Tag == EitherType.Right ? ((Right<TLeft, TRight>)this).Value : default;
50
51 return Tag == EitherType.Right;
52 }
53
54#endregion
55 }
56
57#if !CSX_EITHER_INTERNAL
58 public
59#endif
60 internal sealed class Left<TLeft, TRight> : Either<TLeft, TRight>
61 {
62 internal Left(TLeft value)
63 : base(EitherType.Left)
64 {
65 Value = value;
66 }
67
68 public TLeft Value { get; }
69 }
70
71#if !CSX_EITHER_INTERNAL
72 public
73#endif
74 internal sealed class Right<TLeft, TRight> : Either<TLeft, TRight>
75 {
76 internal Right(TRight value)
77 : base(EitherType.Right)
78 {
79 Value = value;
80 }
81
82 public TRight Value { get; }
83 }
84
85#endregion
86
87#if !CSX_EITHER_INTERNAL
88 public
89#endif
90 internal static class Either
91 {
92#region Functor
93
99 Func<TRight, TResult> func)
100 {
101 TRight right;
102
103 if (either.MatchRight(out right))
104 {
105 return Right<TLeft, TResult>(func(right));
106 }
107
108 return Left<TLeft, TResult>(either.GetLeft());
109 }
110
111#endregion
112
113#region Bifunctor
114
121 Func<TLeft, TLeft1> mapLeft,
122 Func<TRight, TRight1> mapRight)
123 {
124 TRight right;
125
126 if (either.MatchRight(out right))
127 {
128 return Right<TLeft1, TRight1>(mapRight(right));
129 }
130
131 return Left<TLeft1, TRight1>(mapLeft(either.GetLeft()));
132 }
133
134#endregion
135
140 {
141 TRight value;
142
143 if (either.MatchRight(out value))
144 {
145 return value;
146 }
147
148 throw new ArgumentException(nameof(either), string.Format("The either value was Left {0}", either));
149 }
150
154 public static TLeft GetLeftOrDefault<TLeft, TRight>(Either<TLeft, TRight> either, TLeft @default)
155 {
156 TLeft value;
157
158 return either.MatchLeft(out value) ? value : @default;
159 }
160
164 public static TRight GetRightOrDefault<TLeft, TRight>(Either<TLeft, TRight> either, TRight @default)
165 {
166 TRight value;
167
168 return either.MatchRight(out value) ? value : @default;
169 }
170
174 public static Either<Exception, TRight> Try<TRight>(Func<TRight> func)
175 {
176 try
177 {
178 return new Right<Exception, TRight>(func());
179 }
180 catch (Exception ex)
181 {
182 return new Left<Exception, TRight>(ex);
183 }
184 }
185
190 public static Either<Exception, TRight> Cast<TRight>(object obj)
191 {
192 return Try(() => (TRight)obj);
193 }
194
195#if !CSX_REM_MAYBE_FUNC
197 {
198 if (maybe.Tag == MaybeType.Just)
199 {
200 return Right<TLeft, TRight>(((Just<TRight>)maybe).Value);
201 }
202
203 return Left<TLeft, TRight>(left);
204 }
205#endif
206
207 private static TLeft GetLeft<TLeft, TRight>(this Either<TLeft, TRight> either)
208 {
209 return ((Left<TLeft, TRight>)either).Value;
210 }
211
212#region Value Case Constructors
213
215 {
216 return new Left<TLeft, TRight>(value);
217 }
218
219 public static Either<TLeft, TRight> Right<TLeft, TRight>(TRight value)
220 {
221 return new Right<TLeft, TRight>(value);
222 }
223
224#endregion
225
226#region Monad
227
231 public static Either<string, TRight> Return<TRight>(TRight value)
232 {
233 return Right<string, TRight>(value);
234 }
235
239 public static Either<string, TRight> Fail<TRight>(string message)
240 {
241 throw new Exception(message);
242 }
243
249 Func<TRight, Either<TLeft, TResult>> func)
250 {
251 TRight right;
252
253 if (either.MatchRight(out right))
254 {
255 return func(right);
256 }
257
258 return Left<TLeft, TResult>(either.GetLeft());
259 }
260
261#endregion
262
263#region Linq Operators
264
269 Func<TRight, TResult> selector)
270 {
271 return Map(either, selector);
272 }
273
275 Func<TRight, Either<TLeft, TResult>> func)
276 {
277 return Bind(result, func);
278 }
279
280#endregion
281 }
282
283#if !CSX_EITHER_INTERNAL
284 public
285#endif
286 internal static class EitherExtensions
287 {
288#region Alternative Match Methods
289
290 public static void Match<TLeft, TRight>(this Either<TLeft, TRight> either,
291 Action<TLeft> ifLeft,
292 Action<TRight> ifRight)
293 {
294 TLeft left;
295
296 if (either.MatchLeft(out left))
297 {
298 ifLeft(left);
299
300 return;
301 }
302
303 ifRight(((Right<TLeft, TRight>)either).Value);
304 }
305
306#endregion
307
312 public static Either<string, TRight> ToEither<TRight>(this TRight value)
313 {
314 return Either.Return(value);
315 }
316
318 Func<TRight, Either<TLeft, TResult>> func)
319 {
320 return Either.Bind(either, func);
321 }
322
324 Func<TRight, TResult> func)
325 {
326 return Either.Map(either, func);
327 }
328
330 Func<TLeft, TLeft1> mapLeft,
331 Func<TRight, TRight1> mapRight)
332 {
333 return Either.Bimap(either, mapLeft, mapRight);
334 }
335
336 public static bool IsLeft<TLeft, TRight>(this Either<TLeft, TRight> either)
337 {
338 return either.Tag == EitherType.Left;
339 }
340
341 public static bool IsRight<TLeft, TRight>(this Either<TLeft, TRight> either)
342 {
343 return either.Tag == EitherType.Right;
344 }
345 }
346}
static Either< TLeft, TResult > Bind< TLeft, TRight, TResult >(this Either< TLeft, TRight > either, Func< TRight, Either< TLeft, TResult > > func)
Definition Either.cs:317
static Either< string, TRight > ToEither< TRight >(this TRight value)
Equivalent to monadic CSharpx.Either.Return<TRight> operation. Builds a CSharpx.Right<TLeft,...
Definition Either.cs:312
static void Match< TLeft, TRight >(this Either< TLeft, TRight > either, Action< TLeft > ifLeft, Action< TRight > ifRight)
Definition Either.cs:290
static bool IsLeft< TLeft, TRight >(this Either< TLeft, TRight > either)
Definition Either.cs:336
static Either< TLeft, TResult > Map< TLeft, TRight, TResult >(this Either< TLeft, TRight > either, Func< TRight, TResult > func)
Definition Either.cs:323
static Either< TLeft1, TRight1 > Bimap< TLeft, TRight, TLeft1, TRight1 >(this Either< TLeft, TRight > either, Func< TLeft, TLeft1 > mapLeft, Func< TRight, TRight1 > mapRight)
Definition Either.cs:329
static bool IsRight< TLeft, TRight >(this Either< TLeft, TRight > either)
Definition Either.cs:341
static TRight GetOrFail< TLeft, TRight >(Either< TLeft, TRight > either)
Returns a Either Right or fail with an exception.
Definition Either.cs:139
static Either< TLeft, TRight > Left< TLeft, TRight >(TLeft value)
Definition Either.cs:214
EitherType Tag
Definition Either.cs:36
static Either< TLeft, TResult > Map< TLeft, TRight, TResult >(Either< TLeft, TRight > either, Func< TRight, TResult > func)
Transforms a Either's right value by using a specified mapping function.
Definition Either.cs:97
bool MatchRight(out TRight value)
Definition Either.cs:47
static Either< string, TRight > Return< TRight >(TRight value)
Inject a value into the Either type, returning Right case.
Definition Either.cs:231
static TLeft GetLeft< TLeft, TRight >(this Either< TLeft, TRight > either)
Definition Either.cs:207
static TRight GetRightOrDefault< TLeft, TRight >(Either< TLeft, TRight > either, TRight @default)
Returns a Either Right or a defualt value.
Definition Either.cs:164
static Either< TLeft1, TRight1 > Bimap< TLeft, TRight, TLeft1, TRight1 >(Either< TLeft, TRight > either, Func< TLeft, TLeft1 > mapLeft, Func< TRight, TRight1 > mapRight)
Maps both parts of a Either type. Applies the first function if Either is Left. Otherwise applies the...
Definition Either.cs:119
Either(EitherType tag)
Definition Either.cs:31
static TLeft GetLeftOrDefault< TLeft, TRight >(Either< TLeft, TRight > either, TLeft @default)
Returns a Either Left or a defualt value.
Definition Either.cs:154
static Either< TLeft, TResult > Select< TLeft, TRight, TResult >(this Either< TLeft, TRight > either, Func< TRight, TResult > selector)
Map operation compatible with Linq.
Definition Either.cs:268
static Either< TLeft, TRight > Right< TLeft, TRight >(TRight value)
Definition Either.cs:219
static Either< Exception, TRight > Try< TRight >(Func< TRight > func)
Wraps a function, encapsulates any exception thrown within to a Either.
Definition Either.cs:174
bool MatchLeft(out TLeft value)
Definition Either.cs:40
static Either< TLeft, TResult > SelectMany< TLeft, TRight, TResult >(this Either< TLeft, TRight > result, Func< TRight, Either< TLeft, TResult > > func)
Definition Either.cs:274
static Either< Exception, TRight > Cast< TRight >(object obj)
Attempts to cast an object. Stores the cast value in 1Of2 if successful, otherwise stores the excepti...
Definition Either.cs:190
static Either< string, TRight > Fail< TRight >(string message)
Fail with a message. Not part of mathematical definition of a monad.
Definition Either.cs:239
static Either< TLeft, TRight > FromMaybe< TLeft, TRight >(Maybe< TRight > maybe, TLeft left)
Definition Either.cs:196
static Either< TLeft, TResult > Bind< TLeft, TRight, TResult >(Either< TLeft, TRight > either, Func< TRight, Either< TLeft, TResult > > func)
Monadic bind.
Definition Either.cs:247
Models a CSharpx.Maybe when contains a value.
Definition Maybe.cs:88
Left(TLeft value)
Definition Either.cs:62
TLeft Value
Definition Either.cs:68
The Maybe type models an optional value. A value of type Maybe a either contains a value of type a (r...
Definition Maybe.cs:33
MaybeType Tag
Type discriminator.
Definition Maybe.cs:42
TRight Value
Definition Either.cs:82
Right(TRight value)
Definition Either.cs:76
EitherType
Definition Either.cs:14
MaybeType
Discriminator for CSharpx.Maybe.
Definition Maybe.cs:19