2 using JetBrains.Annotations;
6 public static class Either
8 internal const string DefaultCtorError =
"Don't use the default constructor!";
42 public struct Either<TLeft, TRight>
47 private readonly TLeft _error;
52 private readonly EitherState _state;
57 private readonly TRight _val;
63 internal Either(TRight val)
65 _state = EitherState.IsRight;
67 _error =
default(TLeft);
74 internal Either(TLeft error)
76 _state = EitherState.IsLeft;
77 _val =
default(TRight);
91 case EitherState.IsRight:
93 case EitherState.IsLeft:
96 throw new InvalidOperationException(Either.DefaultCtorError);
108 public Either<TLeft, TResult> Select<TResult>([NotNull] Func<TRight, TResult> fn)
112 case EitherState.IsRight:
113 return new Either<TLeft, TResult>(fn(_val));
114 case EitherState.IsLeft:
115 return new Either<TLeft, TResult>(_error);
117 throw new InvalidOperationException(Either.DefaultCtorError);
132 case EitherState.IsRight:
135 case EitherState.IsLeft:
138 throw new InvalidOperationException(Either.DefaultCtorError);
143 public Either<TLeft, TResSuccess> SelectMany<TResSuccess>(
144 [NotNull] Func<TRight, Either<TLeft, TResSuccess>> fn)
148 case EitherState.IsRight:
150 case EitherState.IsLeft:
151 return new Either<TLeft, TResSuccess>(_error);
153 throw new InvalidOperationException(Either.DefaultCtorError);
158 public Either<TLeft, TResSuccess> SelectMany<TInner, TResSuccess>(
159 [NotNull] Func<TRight, Either<TLeft, TInner>> firstFn,
160 [NotNull] Func<TRight, TInner, TResSuccess> secondFn)
162 return SelectMany(x => firstFn(x).SelectMany(y =>
163 new Either<TLeft, TResSuccess>(secondFn(x, y))));
175 public TResult Match<TResult>(
176 [NotNull] Func<TRight, TResult> right,
177 [NotNull] Func<TLeft, TResult> left)
181 case EitherState.IsRight:
183 case EitherState.IsLeft:
186 throw new InvalidOperationException(Either.DefaultCtorError);
199 [NotNull] Action<TRight> right,
200 [NotNull] Action<TLeft> left)
204 case EitherState.IsRight:
207 case EitherState.IsLeft:
211 throw new InvalidOperationException(Either.DefaultCtorError);
220 case EitherState.IsRight:
221 return string.Format(
"Right {0}", _val);
222 case EitherState.IsLeft:
223 return string.Format(
"Left {0}", _error);
225 return "Invalid Either";
237 left: _ => Maybe.Nothing<TRight>(),
244 private enum EitherState
Either< TLeft, TRight > Select_([NotNull] Action< TRight > fn)
Apply the given function to the possibly present val and throw away the result. Otherwise, don't do anything.
Either< TLeft, TRight > Match_([NotNull] Action< TRight > right, [NotNull] Action< TLeft > left)
Apply the function success to the val if present. Otherwise, apply the function failure to the error ...
Property</c ></item > *< item >< c > value
override string ToString()
TRight GetOrElse(TRight other)
Get the stored val or the given default instead.
Maybe< TRight > ToMaybe()
Convert either to Maybe.
An Either wraps the result of a computation that can fail or the resulting error val. The subtype 'Right' represents a successful result wrapping the val whereas the 'Left' subtype represents a failed computation with the resulting error val.