Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageVersion Include="NSubstitute" Version="5.0.0" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.16" />
<PackageVersion Include="Rnd" Version="8.4.4" />
<PackageVersion Include="xunit" Version="2.4.2" />
<PackageVersion Include="xunit.assert" Version="2.4.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
<PackageVersion Include="Rnd" Version="8.4.5" />
<PackageVersion Include="xunit" Version="2.5.0" />
<PackageVersion Include="xunit.assert" Version="2.5.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.0" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion Version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.3.3
9.3.4
15 changes: 15 additions & 0 deletions src/MaybeF/EnumerableExtensions.BindAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Maybe: .NET Monad.
// Copyright (c) bfren - licensed under https://mit.bfren.dev/2019

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MaybeF;

public static partial class EnumerableExtensions
{
/// <inheritdoc cref="F.EnumerableF.BindAsync{T, TReturn}(IEnumerable{Maybe{T}}, Func{T, Task{Maybe{TReturn}}})"/>
public static IAsyncEnumerable<Maybe<TReturn>> BindAsync<T, TReturn>(IEnumerable<Maybe<T>> @this, Func<T, Task<Maybe<TReturn>>> bind) =>
F.EnumerableF.BindAsync(@this, bind);
}
15 changes: 15 additions & 0 deletions src/MaybeF/EnumerableExtensions.MapAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Maybe: .NET Monad.
// Copyright (c) bfren - licensed under https://mit.bfren.dev/2019

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MaybeF;

public static partial class EnumerableExtensions
{
/// <inheritdoc cref="F.EnumerableF.MapAsync{T, TReturn}(IEnumerable{T}, Func{T, Task{Maybe{TReturn}}})"/>
public static IAsyncEnumerable<Maybe<TReturn>> MapAsync<T, TReturn>(IEnumerable<T> @this, Func<T, Task<Maybe<TReturn>>> map) =>
F.EnumerableF.MapAsync(@this, map);
}
7 changes: 5 additions & 2 deletions src/MaybeF/Functions/F.EnumerableF.Bind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ public static IEnumerable<Maybe<TReturn>> Bind<T, TReturn>(IEnumerable<Maybe<T>>

foreach (var item in list)
{
foreach (var value in F.Bind(item, bind))
foreach (var value in item)
{
yield return value;
if (value is not null)
{
yield return bind(value);
}
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions src/MaybeF/Functions/F.EnumerableF.BindAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Maybe: .NET Monad.
// Copyright (c) bfren - licensed under https://mit.bfren.dev/2019

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MaybeF;

public static partial class F
{
public static partial class EnumerableF
{
/// <inheritdoc cref="Bind{T, TReturn}(IEnumerable{Maybe{T}}, Func{T, Maybe{TReturn}})"/>
public static async IAsyncEnumerable<Maybe<TReturn>> BindAsync<T, TReturn>(IEnumerable<Maybe<T>> list, Func<T, Task<Maybe<TReturn>>> bind)
{
if (list is null || bind is null)
{
yield break;
}

foreach (var item in list)
{
foreach (var value in item)
{
if (value is not null)
{
yield return await bind(value);
}
}
}
}
}
}
34 changes: 34 additions & 0 deletions src/MaybeF/Functions/F.EnumerableF.MapAsync.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Maybe: .NET Monad.
// Copyright (c) bfren - licensed under https://mit.bfren.dev/2019

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace MaybeF;

public static partial class F
{
public static partial class EnumerableF
{
/// <inheritdoc cref="Map{T, TReturn}(IEnumerable{T}, Func{T, Maybe{TReturn}})"/>
public static async IAsyncEnumerable<Maybe<TReturn>> MapAsync<T, TReturn>(IEnumerable<T> list, Func<T, Task<Maybe<TReturn>>> map)
{
if (list is null || map is null)
{
yield break;
}

foreach (var item in list)
{
if (item is not null)
{
await foreach (var value in map(item))
{
yield return value;
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Maybe: Unit Tests
// Copyright (c) bfren - licensed under https://mit.bfren.dev/2019

using MaybeF;

namespace Abstracts.Enumerable;

public abstract class BindAsync_Tests
{
public abstract Task Test00_Removes_None_Input_Items();

protected static async Task Test00(Func<IEnumerable<Maybe<int>>, Func<int, Task<Maybe<string>>>, IAsyncEnumerable<Maybe<string>>> act)
{
// Arrange
var i0 = F.Some(Rnd.Int);
var i1 = F.Some(Rnd.Int);
var i2 = Create.None<int>();
var list = new[] { i0, i1, i2 };
var bind = Substitute.For<Func<int, Task<Maybe<string>>>>();
bind.Invoke(default).ReturnsForAnyArgs(x => x.Arg<int>().ToString());

// Act
List<Maybe<string>> result = new();
await foreach (var item in act(list, bind))
{
result.Add(item);
}

// Assert
Assert.Collection(result,
x => Assert.Equal(i0.ToString(), x.AssertSome()),
x => Assert.Equal(i1.ToString(), x.AssertSome())
);
}

public abstract Task Test01_Binds_Each_Item();

protected static async Task Test01(Func<IEnumerable<Maybe<int>>, Func<int, Task<Maybe<string>>>, IAsyncEnumerable<Maybe<string>>> act)
{
// Arrange
var i0 = F.Some(Rnd.Int);
var i1 = F.Some(Rnd.Int);
var i2 = F.Some(Rnd.Int);
var list = new[] { i0, i1, i2 };
var bind = Substitute.For<Func<int, Task<Maybe<string>>>>();
bind.Invoke(default).ReturnsForAnyArgs(x => x.Arg<int>().ToString());

// Act
List<Maybe<string>> result = new();
await foreach (var item in act(list, bind))
{
result.Add(item);
}

// Assert
Assert.Collection(result,
x => Assert.Equal(i0.ToString(), x.AssertSome()),
x => Assert.Equal(i1.ToString(), x.AssertSome()),
x => Assert.Equal(i2.ToString(), x.AssertSome())
);
}

public abstract Task Test02_List_Null_Returns_Empty_List();

protected static async Task Test02(Func<IEnumerable<Maybe<int>>, Func<int, Task<Maybe<string>>>, IAsyncEnumerable<Maybe<string>>> act)
{
// Arrange
var bind = Substitute.For<Func<int, Task<Maybe<string>>>>();

// Act
List<Maybe<string>> result = new();
await foreach (var item in act(null!, bind))
{
result.Add(item);
}

// Assert
Assert.Empty(result);
}

public abstract Task Test03_Map_Null_Returns_Empty_List();

protected static async Task Test03(Func<IEnumerable<Maybe<int>>, Func<int, Task<Maybe<string>>>, IAsyncEnumerable<Maybe<string>>> act)
{
// Arrange
var list = new[] { F.Some(Rnd.Int), F.Some(Rnd.Int), F.Some(Rnd.Int) };

// Act
List<Maybe<string>> result = new();
await foreach (var item in act(list, null!))
{
result.Add(item);
}

// Assert
Assert.Empty(result);
}
}
39 changes: 5 additions & 34 deletions tests/Tests.MaybeF/- Test Abstracts -/Enumerable/Bind_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,9 @@ protected static void Test00(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<strin
);
}

public abstract void Test01_Removes_None_Bound_Items();
public abstract void Test01_Binds_Each_Item();

protected static void Test01(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<string>>, IEnumerable<Maybe<string>>> act)
{
// Arrange
var i0 = F.Some(Rnd.Int);
var i1 = F.Some(Rnd.Int);
var i2 = F.Some(Rnd.Int);
var list = new[] { i0, i1, i2 };
var bind = Substitute.For<Func<int, Maybe<string>>>();
bind.Invoke(default).ReturnsForAnyArgs(x => x.Arg<int>() switch
{
int y when i2.IsSome(out var z) && y == z =>
Create.None<string>(),

int y =>
y.ToString()
});

// Act
var result = act(list, bind);

// Assert
Assert.Collection(result,
x => Assert.Equal(i0.ToString(), x.AssertSome()),
x => Assert.Equal(i1.ToString(), x.AssertSome())
);
}

public abstract void Test02_Binds_Each_Item();

protected static void Test02(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<string>>, IEnumerable<Maybe<string>>> act)
{
// Arrange
var i0 = F.Some(Rnd.Int);
Expand All @@ -81,9 +52,9 @@ protected static void Test02(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<strin
);
}

public abstract void Test03_List_Null_Returns_Empty_List();
public abstract void Test02_List_Null_Returns_Empty_List();

protected static void Test03(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<string>>, IEnumerable<Maybe<string>>> act)
protected static void Test02(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<string>>, IEnumerable<Maybe<string>>> act)
{
// Arrange
var bind = Substitute.For<Func<int, Maybe<string>>>();
Expand All @@ -96,9 +67,9 @@ protected static void Test03(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<strin
Assert.Empty(result);
}

public abstract void Test04_Map_Null_Returns_Empty_List();
public abstract void Test03_Map_Null_Returns_Empty_List();

protected static void Test04(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<string>>, IEnumerable<Maybe<string>>> act)
protected static void Test03(Func<IEnumerable<Maybe<int>>, Func<int, Maybe<string>>, IEnumerable<Maybe<string>>> act)
{
// Arrange
var list = new[] { F.Some(Rnd.Int), F.Some(Rnd.Int), F.Some(Rnd.Int) };
Expand Down
12 changes: 3 additions & 9 deletions tests/Tests.MaybeF/Functions/Enumerable/Bind_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,20 @@ public override void Test00_Removes_None_Input_Items()
}

[Fact]
public override void Test01_Removes_None_Bound_Items()
public override void Test01_Binds_Each_Item()
{
Test01(F.EnumerableF.Bind);
}

[Fact]
public override void Test02_Binds_Each_Item()
public override void Test02_List_Null_Returns_Empty_List()
{
Test02(F.EnumerableF.Bind);
}

[Fact]
public override void Test03_List_Null_Returns_Empty_List()
public override void Test03_Map_Null_Returns_Empty_List()
{
Test03(F.EnumerableF.Bind);
}

[Fact]
public override void Test04_Map_Null_Returns_Empty_List()
{
Test04(F.EnumerableF.Bind);
}
}
12 changes: 3 additions & 9 deletions tests/Tests.MaybeF/_/EnumerableExtensions/Bind_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,20 @@ public override void Test00_Removes_None_Input_Items()
}

[Fact]
public override void Test01_Removes_None_Bound_Items()
public override void Test01_Binds_Each_Item()
{
Test01((list, bind) => list.Bind(bind));
}

[Fact]
public override void Test02_Binds_Each_Item()
public override void Test02_List_Null_Returns_Empty_List()
{
Test02((list, bind) => list.Bind(bind));
}

[Fact]
public override void Test03_List_Null_Returns_Empty_List()
public override void Test03_Map_Null_Returns_Empty_List()
{
Test03((list, bind) => list.Bind(bind));
}

[Fact]
public override void Test04_Map_Null_Returns_Empty_List()
{
Test04((list, bind) => list.Bind(bind));
}
}