-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Result): extension methods to enumerables of Result
- Loading branch information
1 parent
772905d
commit b0ba796
Showing
14 changed files
with
289 additions
and
136 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Bogoware Monads Changelog | ||
|
||
## 9.0.0 | ||
|
||
### New Features | ||
|
||
- The following extension methods on `IEnumerable<Result<T>>` have been introduced: | ||
- `MapEach`: maps each `Result` in the sequence, preserving the failed `Result`s | ||
- `BindEach`: binds each `Result` in the sequence, preserving the failed `Result`s | ||
- `MatchEach`: matches each `Result` in the sequence | ||
- `AggregateResult`: transforms a sequence of `Result`s into a single `Result` that contains a sequence of the successful values. If the original sequence contains any `Error` then will return a failed `Result` with an `AggregateError` containing all the errors found. | ||
|
||
### Breaking Changes | ||
- The following extension methods on `IEnumerable<Result<T>>` have been removed: | ||
- `Map`: use `MapEach` instead. The latter will preserve the failed `Result`s | ||
- `Bind`: use `BindEach` instead. The latter will preserve the failed `Result`s | ||
- `Macth` renamed to `MatchEach`. |
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
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
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
This file was deleted.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// ReSharper disable UnusedTypeParameter | ||
namespace Bogoware.Monads; | ||
|
||
/// <summary> | ||
|
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
namespace Bogoware.Monads; | ||
|
||
/// <summary> | ||
/// Represents a collection of <see cref="Result{TValue}"/>s. | ||
/// </summary> | ||
internal class ResultCollection<TValue> | ||
{ | ||
public bool IsSuccess { get; } | ||
public bool IsFailure => !IsSuccess; | ||
public Error GetErrorOrThrow() => _error ?? throw new ResultSuccessException(); | ||
|
||
private readonly List<Result<TValue>> _results; | ||
private readonly AggregateError? _error; | ||
|
||
internal ResultCollection(IEnumerable<Result<TValue>> results) | ||
{ | ||
_results = [..results]; | ||
IsSuccess = _results.Count == 0 | ||
|| _results.All(r => r.IsSuccess); | ||
|
||
if (IsSuccess) return; | ||
|
||
var errors = _results.Where(r => r.IsFailure).Select(r => r.GetErrorOrThrow()); | ||
_error = new (errors); | ||
} | ||
|
||
internal Result<IEnumerable<TValue?>> ToResult() | ||
{ | ||
if (IsFailure) return Result.Failure<IEnumerable<TValue?>>(_error); | ||
if (_results.Count == 0) return Result.Success(Enumerable.Empty<TValue?>()); | ||
var values = _results.Select(r => r.Value); | ||
return Result.Success(values); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace Bogoware.Monads; | ||
|
||
public static partial class ResultEnumerableExtensions | ||
{ | ||
|
||
/// <summary> | ||
/// Filters <c>Success</c>es via the predicate. | ||
/// <c>Failure</c>s are discarded. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<Result<TValue>> Where<TValue>( | ||
this IEnumerable<Result<TValue>> successes, Func<TValue, bool> predicate) | ||
=> successes.SelectValues() | ||
.Where(predicate) | ||
.Select(v => new Result<TValue>(v)); | ||
|
||
/// <summary> | ||
/// Filters <c>Success</c>es via negated predicate. | ||
/// <c>Failure</c>s are discarded. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<Result<TValue>> WhereNot<TValue>( | ||
this IEnumerable<Result<TValue>> successes, Func<TValue, bool> predicate) | ||
=> successes.SelectValues() | ||
.Where(v => !predicate(v)) | ||
.Select(v => new Result<TValue>(v)); | ||
|
||
} |
57 changes: 57 additions & 0 deletions
57
src/Monads/Result/ResultEnumerableExtensions.Predicates.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
// ReSharper disable MemberCanBePrivate.Global | ||
|
||
namespace Bogoware.Monads; | ||
|
||
public static partial class ResultEnumerableExtensions | ||
{ | ||
/// <summary> | ||
/// Determines if all <see cref="Result{TValue}"/>s of a sequence are <c>Success</c>s. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AllSuccess(this IEnumerable<IResult> successes) | ||
=> successes.All(r => r.IsSuccess); | ||
|
||
/// <inheritdoc cref="AllSuccess"/> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AllSuccess<TValue>(this IEnumerable<Result<TValue>> successes) | ||
=> successes.All(v => v.IsSuccess); | ||
|
||
/// <summary> | ||
/// Determines if all <see cref="Result{TValue}"/>s of a sequence are <c>Failure</c>s. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AllFailure(this IEnumerable<IResult> successes) | ||
=> successes.All(r => r.IsFailure); | ||
|
||
/// <inheritdoc cref="AllFailure"/> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AllFailure<TValue>(this IEnumerable<Result<TValue>> successes) | ||
=> successes.All(v => v.IsFailure); | ||
|
||
/// <summary> | ||
/// Determines if any <see cref="Result{TValue}"/> of a sequence is <c>Success</c>. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AnySuccess(this IEnumerable<IResult> successes) | ||
=> successes.Any(r => r.IsSuccess); | ||
|
||
/// <inheritdoc cref="AnySuccess"/> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AnySuccess<TValue>(this IEnumerable<Result<TValue>> successes) | ||
=> successes.Any(v => v.IsSuccess); | ||
|
||
/// <summary> | ||
/// Determines if any <see cref="Result{TValue}"/> of a sequence is <c>Failure</c>. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AnyFailure(this IEnumerable<IResult> successes) | ||
=> successes.Any(r => r.IsFailure); | ||
|
||
/// <inheritdoc cref="AnyFailure"/> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static bool AnyFailure<TValue>(this IEnumerable<Result<TValue>> successes) | ||
=> successes.Any(v => v.IsFailure); | ||
|
||
} |
61 changes: 61 additions & 0 deletions
61
src/Monads/Result/ResultEnumerableExtensions.SelectValues.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace Bogoware.Monads; | ||
|
||
public static partial class ResultEnumerableExtensions | ||
{ | ||
|
||
/// <summary> | ||
/// Extract values from <see cref="Result{TValue}"/>s. | ||
/// <c>Failure</c>s are discarded. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<TValue> SelectValues<TValue>(this IEnumerable<Result<TValue>> successes) | ||
=> successes.SelectMany(v => v); | ||
|
||
/// <summary> | ||
/// Maps values via the functor. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<Result<TNewValue>> MapEach<TValue, TNewValue>( | ||
this IEnumerable<Result<TValue>> results, Func<TValue, TNewValue> functor) | ||
=> results.Select(result => result.Map(functor)); | ||
|
||
/// <summary> | ||
/// Bind values via the functor. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<Result<TNewValue>> BindEach<TValue, TNewValue>( | ||
this IEnumerable<Result<TValue>> results, Func<TValue, Result<TNewValue>> functor) | ||
=> results.Select(result => result.Bind(functor)); | ||
|
||
/// <summary> | ||
/// Matches results. | ||
/// </summary> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<TResult> MatchEach<TValue, TResult>( | ||
this IEnumerable<Result<TValue>> results, | ||
Func<TValue, TResult> mapSuccesses, | ||
Func<Error, TResult> mapFailures) | ||
=> results.Select(result => result.Match(mapSuccesses, mapFailures)); | ||
|
||
/// <inheritdoc cref="MatchEach{TValue,TResult}(System.Collections.Generic.IEnumerable{Bogoware.Monads.Result{TValue}},System.Func{TValue,TResult},System.Func{Bogoware.Monads.Error,TResult})"/> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static IEnumerable<TResult> MatchEach<TValue, TResult>( | ||
this IEnumerable<Result<TValue>> results, | ||
Func<TValue, TResult> mapSuccesses, | ||
TResult failure) | ||
=> results.Select(result => result.Match(mapSuccesses, failure)); | ||
|
||
/// <summary> | ||
/// Aggregates an enumeration of Result into a Result of an enumeration. | ||
/// If all <see cref="Result{TValue}"/>s are <c>Success</c> then return a <c>Success</c> <see cref="Result{TValue}"/>. | ||
/// otherwise return a <c>Failure</c> with an <see cref="AggregateError"/>. | ||
/// </summary> | ||
/// <param name="results"></param> | ||
/// <typeparam name="TValue"></typeparam> | ||
/// <returns></returns> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static Result<IEnumerable<TValue?>> AggregateResult<TValue>(this IEnumerable<Result<TValue>> results) | ||
=> new ResultCollection<TValue>(results).ToResult(); | ||
} |
Oops, something went wrong.