diff --git a/EasyMonads.Test/EitherTests/QueryTests/IEnumerableSelectTests.cs b/EasyMonads.Test/EitherTests/QueryTests/IEnumerableSelectTests.cs new file mode 100644 index 0000000..1599f32 --- /dev/null +++ b/EasyMonads.Test/EitherTests/QueryTests/IEnumerableSelectTests.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using NUnit.Framework; + +namespace EasyMonads.Test.EitherTests.QueryTests +{ + [TestFixture] + internal class IEnumerableSelectTests + { + [Test] + public void Select_Works_For_IEnumerable_Either() + { + Dictionary resultDict = new Dictionary + { + { 0, "0" }, + { 1, "1" }, + { 2, "2" } + }; + + IEnumerable> results = from number in GetRange() + from text in ConvertToString(number) + select text; + + foreach (var result in results.Select((x, i) => new { Value = x, Index = i })) + { + result.Value.DoRight(x => Assert.AreEqual(resultDict[result.Index], x)); + result.Value.DoLeftOrNeither(Assert.Fail); + } + + return; + + IEnumerable> GetRange() + { + foreach (var entry in resultDict) + { + yield return entry.Key; + } + } + + Either ConvertToString(int number) + { + return number.ToString(); + } + } + + [Test] + public async Task Select_Works_For_Async_IEnumerable_Either() + { + Dictionary resultDict = new Dictionary + { + { 0, "0" }, + { 1, "1" }, + { 2, "2" } + }; + + IEnumerable> results = await + from number in GetRangeAsync() + from text in ConvertToString(number) + select text; + + foreach (var result in results.Select((x, i) => new { Value = x, Index = i })) + { + result.Value.DoRight(x => Assert.AreEqual(resultDict[result.Index], x)); + result.Value.DoLeftOrNeither(Assert.Fail); + } + + return; + + Task>> GetRangeAsync() + { + return resultDict.Select(x => Either.FromRight(x.Key)).AsTask(); + } + + Either ConvertToString(int number) + { + return Either.From(number.ToString()); + } + } + } +} \ No newline at end of file diff --git a/EasyMonads/Either/EitherAsyncExtensions.cs b/EasyMonads/Either/EitherAsyncExtensions.cs index 2db978f..8226c90 100644 --- a/EasyMonads/Either/EitherAsyncExtensions.cs +++ b/EasyMonads/Either/EitherAsyncExtensions.cs @@ -149,7 +149,9 @@ public static async Task> Select( neither: Either.Neither); } - public static async Task> SelectMany(this Task> either, Func>> bind, Func project) + public static async Task> SelectMany(this Task> either, + Func>> bind, + Func project) { return await either.BindAsync(async right => await bind(right).BindAsync(delegate (TIntermediate intermediate) diff --git a/EasyMonads/Either/EitherEnumerableExtensions.cs b/EasyMonads/Either/EitherEnumerableExtensions.cs new file mode 100644 index 0000000..45f78cc --- /dev/null +++ b/EasyMonads/Either/EitherEnumerableExtensions.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace EasyMonads +{ + public static class EitherEnumerableExtensions + { + public static IEnumerable> Select(this IEnumerable> enumerableEither, Func map) + { + return enumerableEither.Select(either => either.Map(map)); + } + + public static IEnumerable> SelectMany(this IEnumerable> enumerableEither, Func> bind, Func project) + { + return enumerableEither.Select, Either>(either => either.Bind(right => + bind(right).Bind(intermediate => project(right, intermediate)))); + } + + public static IEnumerable>> SelectMany(this IEnumerable>> enumerableAsyncEither, + Func>> bind, Func project) + { + return enumerableAsyncEither.Select(async either => await either.BindAsync(right => + bind(right).BindAsync(intermediate => project(right, intermediate)))); + } + + /* + public static async IAsyncEnumerable> SelectMany( + this IAsyncEnumerable> enumerableEither, + Func, IAsyncEnumerable>> bindAsync, + Func, Either, Either> project) + { + await foreach (Either either in enumerableEither) + { + await foreach (Either intermediate in bindAsync(either)) + { + yield return project(either, intermediate); + } + } + } + + public static async IAsyncEnumerable> SelectMany( + this IAsyncEnumerable> enumerableEither, + Func> bind, + Func project) + { + await foreach (var either in enumerableEither) + { + yield return await either.BindAsync(async right => bind(right).Bind(delegate(TIntermediate intermediate) + { + Either projection = project(right, intermediate); + return projection; + })); + } + } + + public static async IAsyncEnumerable> SelectMany( + this IAsyncEnumerable> enumerableEither, + Func> bind, + Func project) + { + await foreach (var either in enumerableEither) + { + yield return await either.BindAsync(right => bind(right).BindAsync(delegate(TIntermediate intermediate) + { + Either projection = project(right, intermediate); + return projection.AsTask(); + })); + } + } + */ + + public static async Task>> Select(this Task>> asyncEnumerableEither, Func map) + { + return (await asyncEnumerableEither).Select(map); + } + + public static async Task>> SelectMany(this Task>> asyncEnumerableEither, + Func>>> bind, + Func>, TResult> project) + { + return (await asyncEnumerableEither).Select(either => + { + return either.Bind(right => + bind(right).Bind(delegate(Func> intermediate) + { + Either projection = project(right, intermediate); + return projection; + })); + }); + } + + public static IEnumerable>> SelectMany(this IEnumerable>> asyncEnumerableEither, + Func> bind, + Func project) + { + return asyncEnumerableEither.Select(asyncEither => asyncEither.BindAsync(right => bind(right).Bind(delegate(TIntermediate intermediate) + { + Either projection = project(right, intermediate); + return projection; + }))); + } + } +} \ No newline at end of file