-
-
Save zawodskoj/0ec372cafded23e43356edac26584d83 to your computer and use it in GitHub Desktop.
This file contains 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; | |
using System.Runtime.CompilerServices; | |
using System.Threading.Tasks; | |
internal struct MaybeMethodBuilder<T> | |
{ | |
private Maybe<T> _task; | |
public static MaybeMethodBuilder<T> Create() => new MaybeMethodBuilder<T>(); | |
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine | |
{ | |
stateMachine.MoveNext(); | |
} | |
public void SetStateMachine(IAsyncStateMachine stateMachine) | |
{ | |
// idk what is this | |
} | |
public void SetException(Exception exception) | |
{ | |
// just rethrow an exception | |
throw new AggregateException(exception); | |
} | |
public void SetResult(T result) => _task = new Maybe<T>(result); | |
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) | |
where TAwaiter : struct, MaybeAwaiter<T>.IConstraint | |
{ | |
// AwaitOnCompleted call means that `MaybeAwaiter` has `Empty` value | |
// doing nothing | |
} | |
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) | |
where TAwaiter : struct, MaybeAwaiter<T>.IConstraint | |
{ | |
// this method could not be called due to constraints | |
throw new NotSupportedException(); | |
} | |
public Maybe<T> Task => _task; | |
} | |
struct MaybeAwaiter<T> : INotifyCompletion, MaybeAwaiter<T>.IConstraint | |
{ | |
public interface IConstraint { } | |
private readonly Maybe<T> _value; | |
public MaybeAwaiter(Maybe<T> value) => _value = value; | |
public bool IsCompleted => _value.HasValue; | |
public void OnCompleted(Action continuation) {} | |
public T GetResult() => _value.UnwrapOr(default); | |
} | |
[AsyncMethodBuilder(typeof(MaybeMethodBuilder<>))] | |
struct Maybe<T> { | |
private readonly T _value; | |
private readonly bool _hasSmth; | |
public static readonly Maybe<T> Empty = new Maybe<T>(default, false); | |
private Maybe(T value, bool hasSmth) { | |
_value = value; | |
_hasSmth = hasSmth; | |
} | |
public Maybe(T value) : this(value, true) {} | |
public bool HasValue => _hasSmth; | |
public T UnwrapOr(T val) => _hasSmth ? _value : val; | |
public MaybeAwaiter<T> GetAwaiter() => new MaybeAwaiter<T>(this); | |
} | |
class Program | |
{ | |
static async Maybe<int> SumMaybes(Maybe<int> a, Maybe<int> b) | |
{ | |
var av = await a; | |
var bv = await b; | |
return av + bv; | |
} | |
static async Maybe<int> SumMaybesNoThrow() | |
{ | |
await Maybe<int>.Empty; | |
throw new Exception("Should not be thrown"); | |
} | |
static async Maybe<int> SumMaybesAsync(Maybe<int> a, Maybe<int> b) | |
{ | |
await Task.Delay(1000); | |
return await SumMaybes(a, b); | |
} | |
public static void Main() { | |
Console.WriteLine(SumMaybes(new Maybe<int>(123), new Maybe<int>(456)).UnwrapOr(0)); | |
Console.WriteLine(SumMaybesNoThrow().UnwrapOr(-1)); | |
Console.WriteLine(SumMaybesAsync(new Maybe<int>(123), Maybe<int>.Empty).UnwrapOr(-1)); | |
Console.WriteLine("DONE"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment