Skip to content

Commit

Permalink
Added async functions for converting monad types
Browse files Browse the repository at this point in the history
For Maybe to Either conversion:

- Task<Either<TLeft, T>> ToEitherAsync<T, TLeft>(this Maybe<T> maybe, TLeft left)
- Task<Either<TLeft, T>> ToEitherAsync<T, TLeft>(this Task<Maybe<T>> maybeTask, TLeft left)

For Either to Maybe conversion:

- Task<Maybe<TRight>> ToMaybeAsync<TLeft, TRight>(this Either<TLeft, TRight> either)
- Task<Maybe<TRight>> ToMaybeAsync<TLeft, TRight>(this Task<Either<TLeft, TRight>> eitherTask)
  • Loading branch information
apfohl authored and Dirk-Peters committed Aug 6, 2023
1 parent 82c6e24 commit 8604cd5
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 7 deletions.
11 changes: 9 additions & 2 deletions MonadicBits/EitherAsyncExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public static Task<Either<TLeft, TResult>> MapAsync<TLeft, TRight, TResult>(
this Either<TLeft, TRight> either, Func<TRight, Task<TResult>> mapping,
bool continueOnCapturedContext = false) =>
either.Map(mapping).Match(
left => Task.FromResult<Either<TLeft,TResult>>(left.Left()),
left => Task.FromResult<Either<TLeft, TResult>>(left.Left()),
async task => (await task.ConfigureAwait(continueOnCapturedContext)).Right<TLeft, TResult>());

public static Task<Either<TResult, TRight>> MapLeftAsync<TLeft, TRight, TResult>(
Expand Down Expand Up @@ -84,5 +84,12 @@ public static async Task<Either<TResult, TRight>> BindLeftAsync<TLeft, TRight, T
bool continueOnCapturedContext = false) =>
await (await eitherTask.ConfigureAwait(continueOnCapturedContext)).BindLeftAsync(mapping,
continueOnCapturedContext);

public static Task<Maybe<TRight>> ToMaybeAsync<TLeft, TRight>(this Either<TLeft, TRight> either) =>
Task.FromResult(either.ToMaybe());

public static async Task<Maybe<TRight>>
ToMaybeAsync<TLeft, TRight>(this Task<Either<TLeft, TRight>> eitherTask) =>
(await eitherTask).ToMaybe();
}
}
}
8 changes: 7 additions & 1 deletion MonadicBits/MaybeAsyncExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,11 @@ public static async Task<Maybe<TResult>> BindAsync<T, TResult>(this Task<Maybe<T
Func<T, Task<Maybe<TResult>>> mapping, bool continueOnCapturedContext = false) =>
await (await maybeTask.ConfigureAwait(continueOnCapturedContext)).BindAsync(mapping,
continueOnCapturedContext);

public static Task<Either<TLeft, T>> ToEitherAsync<T, TLeft>(this Maybe<T> maybe, TLeft left) =>
Task.FromResult(maybe.ToEither(left));

public static async Task<Either<TLeft, T>> ToEitherAsync<T, TLeft>(this Task<Maybe<T>> maybeTask, TLeft left) =>
(await maybeTask).ToEither(left);
}
}
}
31 changes: 28 additions & 3 deletions MonadicBitsTests/EitherAsyncExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Threading.Tasks;
using FluentAssertions;
using MonadicBits;
using NUnit.Framework;

namespace MonadicBitsTests
{
using static Functional;

public static class EitherAsyncExtensionsTests
{
[Test]
Expand Down Expand Up @@ -76,12 +79,12 @@ public static async Task MapLeftAsync_either_with_right_value_to_async_mapping_r
[Test]
public static void BindAsync_with_null_mapping_throws_exception() =>
Assert.ThrowsAsync<ArgumentNullException>(() =>
"Test".Right<string, string>().BindAsync((Func<string, Task<Either<string, string>>>) null));
"Test".Right<string, string>().BindAsync((Func<string, Task<Either<string, string>>>)null));

[Test]
public static void BindLeftAsync_with_null_mapping_throws_exception() =>
Assert.ThrowsAsync<ArgumentNullException>(() =>
"Test".Left<string, string>().BindLeftAsync((Func<string, Task<Either<string, string>>>) null));
"Test".Left<string, string>().BindLeftAsync((Func<string, Task<Either<string, string>>>)null));

[Test]
public static async Task
Expand Down Expand Up @@ -154,5 +157,27 @@ public static async Task
.BindLeftAsync(_ => Task.FromResult(input.Left<int, string>())))
.Match(i => Assert.AreEqual(input, i), _ => Assert.Fail());
}

[Test]
public static async Task Left_to_async_maybe_returns_nothing_task() =>
(await TestMonads.Left("Test").ToMaybeAsync()).Should().Be(Nothing);

[Test]
public static async Task Right_to_async_maybe_returns_just_task()
{
const string value = "Test";
(await TestMonads.Right(value).ToMaybeAsync()).Should().Be(value.Just());
}

[Test]
public static async Task Left_task_to_async_maybe_returns_nothing_task() =>
(await Task.FromResult(TestMonads.Left("Test")).ToMaybeAsync()).Should().Be(Nothing);

[Test]
public static async Task Right_task_to_async_maybe_returns_just_task()
{
const string value = "Test";
(await Task.FromResult(TestMonads.Right(value)).ToMaybeAsync()).Should().Be(value.Just());
}
}
}
}
34 changes: 33 additions & 1 deletion MonadicBitsTests/MaybeAsyncExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,37 @@ public static async Task BindAsync_maybe_task_with_value_to_async_mapping_return
(await Task.FromResult("Test".Just()).BindAsync(_ => Task.FromResult(input.Just())))
.Should().Be(input.Just());
}

[Test]
public static async Task Just_to_async_either_makes_right_task()
{
const string input = "Test";
var result = input.Just().ToEitherAsync("Left");
(await result).Match(Assert.Fail, right => Assert.AreEqual(input, right));
}

[Test]
public static async Task Nothing_to_async_either_makes_left_task()
{
const string leftInput = "Left";
var result = Nothing<string>().ToEitherAsync(leftInput);
(await result).Match(left => Assert.AreEqual(leftInput, left), Assert.Fail);
}

[Test]
public static async Task Just_task_to_async_either_makes_right_task()
{
const string input = "Test";
var result = Task.FromResult(input.Just()).ToEitherAsync("Left");
(await result).Match(Assert.Fail, right => Assert.AreEqual(input, right));
}

[Test]
public static async Task Nothing_task_to_async_either_makes_left_task()
{
const string leftInput = "Left";
var result = Task.FromResult(Nothing<string>()).ToEitherAsync(leftInput);
(await result).Match(left => Assert.AreEqual(leftInput, left), Assert.Fail);
}
}
}
}

0 comments on commit 8604cd5

Please sign in to comment.