Table of Contents

Class MaybeAsyncExtensionMethods

Namespace
SodaFlow.Functional
Assembly
SodaFlow.Functional.dll

The operations that move a Maybe<T> across an asynchronous step.

[PublicAPI]
public static class MaybeAsyncExtensionMethods
Inheritance
MaybeAsyncExtensionMethods
Inherited Members

Remarks

Maybe<T> speaks asynchronously on the consuming side, through MatchAsync<TResult>(Func<T, Task<TResult>>, Func<Task<TResult>>) and the helpers built on it. What is here is the composing side: the same Map, Bind , Where and ValueOr vocabulary, in the two shapes an asynchronous chain needs. The Async-suffixed members have a function parameter that returns a task, for the step with the await. The members with no suffix have a Task<TResult> of a Maybe<T> as their subject. Thus, a chain with an asynchronous start can continue with no await in the middle of it. It also needs no parentheses:

Maybe<string> name = await id.TryParseInt32()
    .BindAsync(i => repository.FindAsync(i))
    .Map(u => u.Name)
    .Where(n => n.Length > 0);

The function runs only when there is a value, in each case, thus nothing awaits on the empty path. That is also why the empty path gives a cached completed task, and does not allocate one. Each await here does not capture the calling context. Nothing in this file runs caller code on the continuation, because the awaits are only there to put a result in a task again. Thus, a continuation on a captured context costs a hop and gains nothing. It also deadlocks a caller that blocks on the task from this call.

Methods

BindAsync<T, TResult>(Maybe<T>, Func<T, Task<Maybe<TResult>>>)

Transforms the contained value into a second Maybe<T> with an asynchronous function, if there is one, flattening the result.

BindAsync<T, TResult>(Task<Maybe<T>>, Func<T, Task<Maybe<TResult>>>)

Transforms the value the task will give into a second Maybe<T> with an asynchronous function, if it gives one, flattening the result.

Bind<T, TResult>(Task<Maybe<T>>, Func<T, Maybe<TResult>>)

Transforms the value the task will give into a second Maybe<T>, if it gives one, flattening the result.

MapAsync<T, TResult>(Maybe<T>, Func<T, Task<TResult>>)

Transforms the contained value with an asynchronous function, if there is one.

MapAsync<T, TResult>(Task<Maybe<T>>, Func<T, Task<TResult>>)

Transforms the value the task will give with an asynchronous function, if it gives one.

Map<T, TResult>(Task<Maybe<T>>, Func<T, TResult>)

Transforms the value the task will give, if it gives one.

Match<T, TResult>(Task<Maybe<T>>, Func<T, TResult>, Func<TResult>)

Runs one function on the value that the task gives when there is a value, and a different one, and returns its result.

OrElse<T>(Task<Maybe<T>>, Maybe<T>)

Uses a second Maybe<T> when the task gives no value.

ValueOrDefault<T>(Task<Maybe<T>>)

Returns the value the task gives if there is one, and the default for its type otherwise.

ValueOrThrow<T>(Task<Maybe<T>>, Func<Exception>)

Returns the value the task gives if there is one, and throws the exception produced by the given function otherwise.

ValueOr<T>(Task<Maybe<T>>, T)

Returns the value the task gives if there is one, and the given value otherwise.

WhereAsync<T>(Maybe<T>, Func<T, Task<bool>>)

Keeps the contained value only if it satisfies an asynchronous predicate.

WhereAsync<T>(Task<Maybe<T>>, Func<T, Task<bool>>)

Keeps the value the task will give only if it satisfies an asynchronous predicate.

Where<T>(Task<Maybe<T>>, Func<T, bool>)

Keeps the value the task will give only if it satisfies a predicate.