Created
February 9, 2022 08:13
-
-
Save DBalashov/094428002899157b2d9ebb8e3ac093ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace Monads | |
{ | |
/// <summary> | |
/// <code> | |
/// var r = getUserInput(); | |
/// if(y.TryGetValue(out int i1)) | |
/// { | |
/// Console.WriteLine("Successfully parsed: {0}", i1); | |
/// } | |
/// | |
/// или: | |
/// | |
/// getUserInput() | |
/// .Case(succ => Console.WriteLine("Succesfully parsed: {0}", succ), | |
/// fail => Console.WriteLine("Failed parse: {0}", fail)); | |
/// ... | |
/// static Either<int, string> getUserInput() | |
/// { | |
/// var s1 = Console.ReadLine(); | |
/// return int.TryParse(s1, out var value) ? s1 : value; | |
/// } | |
/// </code> | |
/// </summary> | |
/// <typeparam name="L"></typeparam> | |
/// <typeparam name="R"></typeparam> | |
public readonly struct Either<L, R> | |
{ | |
readonly L left; | |
readonly R right; | |
readonly bool isLeft; | |
public Either(R value) | |
{ | |
isLeft = false; | |
left = default; | |
right = value; | |
} | |
public Either(L value) | |
{ | |
isLeft = true; | |
left = value; | |
right = default; | |
} | |
#region TryGetValue | |
public bool TryGetValue(out L value) | |
{ | |
if (isLeft) | |
{ | |
value = left; | |
return true; | |
} | |
value = default; | |
return false; | |
} | |
public bool TryGetValue(out R value) | |
{ | |
if (!isLeft) | |
{ | |
value = right; | |
return true; | |
} | |
value = default; | |
return false; | |
} | |
#endregion | |
#region Case | |
public void Case(Action<L> actionL, Action<R> actionR) | |
{ | |
if (isLeft) actionL(left); | |
else actionR(right); | |
} | |
public RESULT Case<RESULT>(Func<L, RESULT> actionL, Func<R, RESULT> actionR) => | |
isLeft ? actionL(left) : actionR(right); | |
public Task<RESULT> Case<RESULT>(Func<L, Task<RESULT>> actionL, Func<R, Task<RESULT>> actionR) => | |
isLeft ? actionL(left) : actionR(right); | |
#endregion | |
public L GetValueOrDefault(L defaultValue) => isLeft ? left : defaultValue; | |
public R GetValueOrDefault(R defaultValue) => !isLeft ? right : defaultValue; | |
public L GetValueOrDefault(Func<L> defaultValue) => isLeft ? left : defaultValue(); | |
public R GetValueOrDefault(Func<R> defaultValue) => !isLeft ? right : defaultValue(); | |
#region Equals / GetHashCode | |
public override bool Equals(object? obj) => | |
obj is Either<L, R> e && (isLeft == e.isLeft && ((isLeft && Equals(left, e.left)) || (!isLeft && Equals(right, e.right)))); | |
public override int GetHashCode() => isLeft.GetHashCode() ^ (isLeft ? left.GetHashCode() : right.GetHashCode()); | |
#endregion | |
#region L -> Either<L,R> / R -> Either<L,R> | |
public static implicit operator Either<L, R>(L value) => new(value); | |
public static implicit operator Either<L, R>(R value) => new(value); | |
#endregion | |
#if DEBUG | |
public override string ToString() => (isLeft ? left?.ToString() : right?.ToString()) ?? "Empty"; | |
#endif | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment