Skip to content

Commit 5b167d5

Browse files
feature/monads (#43)
Added `Optional<T>` and `Result<T>` monads.
1 parent 8f05895 commit 5b167d5

14 files changed

+2065
-39
lines changed

OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
<TargetFramework>net8.0</TargetFramework>
44
<ImplicitUsings>enable</ImplicitUsings>
55
<Nullable>enable</Nullable>
6-
76
<IsPackable>false</IsPackable>
8-
97
<LangVersion>12</LangVersion>
8+
<IsTestProject>false</IsTestProject>
109
</PropertyGroup>
1110
<ItemGroup>
1211
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>

OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs

+35-31
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using System.Collections.Generic;
1717
using System.Globalization;
1818
using System.Linq;
19+
using System.Numerics;
1920
using OnixLabs.Core.Linq;
2021
using OnixLabs.Core.UnitTests.Data;
2122
using Xunit;
@@ -32,7 +33,7 @@ public void AllEqualByShouldProduceExpectedResultTrue()
3233
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
3334
Record<Guid> element2 = new("abc", 123, Guid.NewGuid());
3435
Record<Guid> element3 = new("abc", 123, Guid.NewGuid());
35-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
36+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
3637

3738
// When
3839
bool result = elements.AllEqualBy(element => element.Text);
@@ -48,7 +49,7 @@ public void AllEqualByShouldProduceExpectedResultFalse()
4849
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
4950
Record<Guid> element2 = new("abc", 123, Guid.NewGuid());
5051
Record<Guid> element3 = new("xyz", 123, Guid.NewGuid());
51-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
52+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
5253

5354
// When
5455
bool result = elements.AllEqualBy(element => element.Text);
@@ -64,7 +65,7 @@ public void AnyEqualByShouldProduceExpectedResultTrue()
6465
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
6566
Record<Guid> element2 = new("abc", 123, Guid.NewGuid());
6667
Record<Guid> element3 = new("xyz", 123, Guid.NewGuid());
67-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
68+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
6869

6970
// When
7071
bool result = elements.AnyEqualBy(element => element.Text);
@@ -80,7 +81,7 @@ public void AnyEqualByShouldProduceExpectedResultFalse()
8081
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
8182
Record<Guid> element2 = new("def", 123, Guid.NewGuid());
8283
Record<Guid> element3 = new("xyz", 123, Guid.NewGuid());
83-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
84+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
8485

8586
// When
8687
bool result = elements.AnyEqualBy(element => element.Text);
@@ -93,11 +94,11 @@ public void AnyEqualByShouldProduceExpectedResultFalse()
9394
public void CountNotShouldProduceExpectedResult()
9495
{
9596
// Given
97+
const int expected = 2;
9698
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
9799
Record<Guid> element2 = new("def", 123, Guid.NewGuid());
98100
Record<Guid> element3 = new("xyz", 456, Guid.NewGuid());
99-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
100-
const int expected = 2;
101+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
101102

102103
// When
103104
int actual = elements.CountNot(element => element.Number == 456);
@@ -123,8 +124,8 @@ public void ForEachShouldProduceExpectedResult()
123124
public void GetContentHashCodeShouldProduceExpectedResultEqual()
124125
{
125126
// Given
126-
IEnumerable<Element> enumerable1 = new[] { new Element(1), new Element(2), new Element(3) };
127-
IEnumerable<Element> enumerable2 = new[] { new Element(1), new Element(2), new Element(3) };
127+
IEnumerable<Element> enumerable1 = [new Element(1), new Element(2), new Element(3)];
128+
IEnumerable<Element> enumerable2 = [new Element(1), new Element(2), new Element(3)];
128129

129130
// When
130131
int hashCode1 = enumerable1.GetContentHashCode();
@@ -138,8 +139,8 @@ public void GetContentHashCodeShouldProduceExpectedResultEqual()
138139
public void GetContentHashCodeShouldProduceExpectedResultDifferent()
139140
{
140141
// Given
141-
IEnumerable<Element> enumerable1 = new[] { new Element(1), new Element(2), new Element(3) };
142-
IEnumerable<Element> enumerable2 = new[] { new Element(3), new Element(2), new Element(1) };
142+
IEnumerable<Element> enumerable1 = [new Element(1), new Element(2), new Element(3)];
143+
IEnumerable<Element> enumerable2 = [new Element(3), new Element(2), new Element(1)];
143144

144145
// When
145146
int hashCode1 = enumerable1.GetContentHashCode();
@@ -153,7 +154,7 @@ public void GetContentHashCodeShouldProduceExpectedResultDifferent()
153154
public void IsEmptyShouldProduceExpectedResultTrue()
154155
{
155156
// Given
156-
IEnumerable<Element> enumerable = Enumerable.Empty<Element>();
157+
IEnumerable<Element> enumerable = [];
157158

158159
// When
159160
bool result = enumerable.IsEmpty();
@@ -166,7 +167,7 @@ public void IsEmptyShouldProduceExpectedResultTrue()
166167
public void IsEmptyShouldProduceExpectedResultFalse()
167168
{
168169
// Given
169-
IEnumerable<Element> enumerable = new[] { new Element() };
170+
IEnumerable<Element> enumerable = [new Element()];
170171

171172
// When
172173
bool result = enumerable.IsEmpty();
@@ -179,7 +180,7 @@ public void IsEmptyShouldProduceExpectedResultFalse()
179180
public void IsNotEmptyShouldProduceExpectedResultTrue()
180181
{
181182
// Given
182-
IEnumerable<Element> enumerable = new[] { new Element() };
183+
IEnumerable<Element> enumerable = [new Element()];
183184

184185
// When
185186
bool result = enumerable.IsNotEmpty();
@@ -192,7 +193,7 @@ public void IsNotEmptyShouldProduceExpectedResultTrue()
192193
public void IsNotEmptyShouldProduceExpectedResultFalse()
193194
{
194195
// Given
195-
IEnumerable<Element> enumerable = Enumerable.Empty<Element>();
196+
IEnumerable<Element> enumerable = [];
196197

197198
// When
198199
bool result = enumerable.IsNotEmpty();
@@ -205,7 +206,7 @@ public void IsNotEmptyShouldProduceExpectedResultFalse()
205206
public void IsSingleShouldProduceExpectedResultTrue()
206207
{
207208
// Given
208-
IEnumerable<Element> enumerable = new[] { new Element() };
209+
IEnumerable<Element> enumerable = [new Element()];
209210

210211
// When
211212
bool result = enumerable.IsSingle();
@@ -218,7 +219,7 @@ public void IsSingleShouldProduceExpectedResultTrue()
218219
public void IsSingleShouldProduceExpectedResultFalseWhenEmpty()
219220
{
220221
// Given
221-
IEnumerable<Element> enumerable = Enumerable.Empty<Element>();
222+
IEnumerable<Element> enumerable = [];
222223

223224
// When
224225
bool result = enumerable.IsSingle();
@@ -231,7 +232,7 @@ public void IsSingleShouldProduceExpectedResultFalseWhenEmpty()
231232
public void IsSingleShouldProduceExpectedResultFalseWhenMoreThanOneElement()
232233
{
233234
// Given
234-
IEnumerable<Element> enumerable = new[] { new Element(), new Element() };
235+
IEnumerable<Element> enumerable = [new Element(), new Element()];
235236

236237
// When
237238
bool result = enumerable.IsSingle();
@@ -244,7 +245,7 @@ public void IsSingleShouldProduceExpectedResultFalseWhenMoreThanOneElement()
244245
public void IsCountEvenShouldProduceExpectedResultTrue()
245246
{
246247
// Given
247-
IEnumerable<Element> enumerable = new[] { new Element(), new Element() };
248+
IEnumerable<Element> enumerable = [new Element(), new Element()];
248249

249250
// When
250251
bool result = enumerable.IsCountEven();
@@ -257,7 +258,7 @@ public void IsCountEvenShouldProduceExpectedResultTrue()
257258
public void IsCountEvenShouldProduceExpectedResultFalse()
258259
{
259260
// Given
260-
IEnumerable<Element> enumerable = new[] { new Element() };
261+
IEnumerable<Element> enumerable = [new Element()];
261262

262263
// When
263264
bool result = enumerable.IsCountEven();
@@ -270,7 +271,7 @@ public void IsCountEvenShouldProduceExpectedResultFalse()
270271
public void IsCountOddShouldProduceExpectedResultTrue()
271272
{
272273
// Given
273-
IEnumerable<Element> enumerable = new[] { new Element() };
274+
IEnumerable<Element> enumerable = [new Element()];
274275

275276
// When
276277
bool result = enumerable.IsCountOdd();
@@ -283,7 +284,7 @@ public void IsCountOddShouldProduceExpectedResultTrue()
283284
public void IsCountOddShouldProduceExpectedResultFalse()
284285
{
285286
// Given
286-
IEnumerable<Element> enumerable = new[] { new Element(), new Element() };
287+
IEnumerable<Element> enumerable = [new Element(), new Element()];
287288

288289
// When
289290
bool result = enumerable.IsCountOdd();
@@ -296,7 +297,7 @@ public void IsCountOddShouldProduceExpectedResultFalse()
296297
public void JoinToStringShouldProduceExpectedResultWithDefaultSeparator()
297298
{
298299
// Given
299-
IEnumerable<object> enumerable = new object[] { 1, 2, 3, 4.5, true, false };
300+
IEnumerable<object> enumerable = [1, 2, 3, 4.5, true, false];
300301
const string expected = "1, 2, 3, 4.5, True, False";
301302

302303
// When
@@ -310,7 +311,7 @@ public void JoinToStringShouldProduceExpectedResultWithDefaultSeparator()
310311
public void JoinToStringShouldProduceExpectedResultWithCustomSeparator()
311312
{
312313
// Given
313-
IEnumerable<object> enumerable = new object[] { 1, 2, 3, 4.5, true, false };
314+
IEnumerable<object> enumerable = [1, 2, 3, 4.5, true, false];
314315
const string expected = "1 *$ 2 *$ 3 *$ 4.5 *$ True *$ False";
315316

316317
// When
@@ -327,7 +328,7 @@ public void NoneShouldProduceExpectedResultTrue()
327328
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
328329
Record<Guid> element2 = new("def", 456, Guid.NewGuid());
329330
Record<Guid> element3 = new("xyz", 789, Guid.NewGuid());
330-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
331+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
331332

332333
// When
333334
bool result = elements.None(element => element.Number == 0);
@@ -343,7 +344,7 @@ public void NoneShouldProduceExpectedResultFalseAny()
343344
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
344345
Record<Guid> element2 = new("def", 456, Guid.NewGuid());
345346
Record<Guid> element3 = new("xyz", 0, Guid.NewGuid());
346-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
347+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
347348

348349
// When
349350
bool result = elements.None(element => element.Number == 0);
@@ -359,7 +360,7 @@ public void NoneShouldProduceExpectedResultFalseAll()
359360
Record<Guid> element1 = new("abc", 0, Guid.NewGuid());
360361
Record<Guid> element2 = new("def", 0, Guid.NewGuid());
361362
Record<Guid> element3 = new("xyz", 0, Guid.NewGuid());
362-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
363+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
363364

364365
// When
365366
bool result = elements.None(element => element.Number == 0);
@@ -371,12 +372,15 @@ public void NoneShouldProduceExpectedResultFalseAll()
371372
[Fact(DisplayName = "IEnumerable.Sum should produce the expected result")]
372373
public void SumShouldProduceExpectedResult()
373374
{
375+
// Required as Sum() already exists for concrete number types.
376+
static T SumProxy<T>(IEnumerable<T> enumerable) where T : INumberBase<T> => enumerable.Sum();
377+
374378
// Given
375379
IEnumerable<decimal> elements = [12.34m, 34.56m, 56.78m];
376380
const decimal expected = 103.68m;
377381

378382
// When
379-
decimal actual = elements.Sum();
383+
decimal actual = SumProxy(elements);
380384

381385
// Then
382386
Assert.Equal(expected, actual);
@@ -406,8 +410,8 @@ public void WhereNotShouldProduceExpectedResult()
406410
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
407411
Record<Guid> element2 = new("def", 456, Guid.NewGuid());
408412
Record<Guid> element3 = new("xyz", 789, Guid.NewGuid());
409-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, element3 };
410-
IEnumerable<Record<Guid>> expected = new[] { element2, element3 };
413+
IEnumerable<Record<Guid>> elements = [element1, element2, element3];
414+
IEnumerable<Record<Guid>> expected = [element2, element3];
411415

412416
// When
413417
IEnumerable<Record<Guid>> actual = elements.WhereNot(element => element.Number == 123);
@@ -422,8 +426,8 @@ public void WhereNotNullShouldProduceExpectedResult()
422426
// Given
423427
Record<Guid> element1 = new("abc", 123, Guid.NewGuid());
424428
Record<Guid> element2 = new("def", 456, Guid.NewGuid());
425-
IEnumerable<Record<Guid>> elements = new[] { element1, element2, null };
426-
IEnumerable<Record<Guid>> expected = new[] { element1, element2 };
429+
IEnumerable<Record<Guid>?> elements = [element1, element2, null];
430+
IEnumerable<Record<Guid>> expected = [element1, element2];
427431

428432
// When
429433
IEnumerable<Record<Guid>> actual = elements.WhereNotNull();

OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<TargetFramework>net8.0</TargetFramework>
44
<IsPackable>false</IsPackable>
55
<LangVersion>12</LangVersion>
6+
<Nullable>enable</Nullable>
67
</PropertyGroup>
78
<ItemGroup>
89
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>

0 commit comments

Comments
 (0)