Skip to content

Commit 77b03ae

Browse files
committed
Normalised globals to be closer to System.Reactive defaults
1 parent 43f4c92 commit 77b03ae

File tree

16 files changed

+233
-201
lines changed

16 files changed

+233
-201
lines changed

src/MorleyDev.Reactive.Monad/EitherIO.cs

Lines changed: 0 additions & 78 deletions
This file was deleted.

src/MorleyDev.Reactive.Monad/Extensions/ObservableExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Reactive.Linq;
23

34
namespace MorleyDev.Reactive.Monad.Extensions
45
{
@@ -8,6 +9,6 @@ public static class ObservableExtensions
89

910
public static MaybeIO<T> ToMaybeIO<T>(this IObservable<T> self) => MaybeIO.From(self);
1011

11-
public static MaybeIO<T> ToMaybeIO<T>(this IObservable<Maybe<T>> self) => MaybeIO.From(self);
12+
public static MaybeIO<T> ToMaybeIO<T>(this IObservable<Maybe<T>> self) => MaybeIO.From(self.SelectMany(s => s));
1213
}
1314
}
Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
using MorleyDev.Reactive.Monad.Extensions;
21
using System;
32
using System.Linq;
43

5-
namespace MorleyDev.Reactive.Monad
4+
namespace MorleyDev.Reactive.Monad.Extra
65
{
76
public class Either<L, R>
87
{
@@ -11,8 +10,8 @@ public class Either<L, R>
1110

1211
private Either(Maybe<Either<L, R>> left, Maybe<Either<L, R>> right)
1312
{
14-
_left = left.AsEnumerable().SelectMany(d => d._left).Concat(right.AsEnumerable().SelectMany(d => d._left)).ToMaybe();
15-
_right = left.AsEnumerable().SelectMany(d => d._right).Concat(right.AsEnumerable().SelectMany(d => d._right)).ToMaybe();
13+
_left = Maybe.Defer(left.AsEnumerable().SelectMany(d => d._left).Concat(right.AsEnumerable().SelectMany(d => d._left)).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single);
14+
_right = Maybe.Defer(left.AsEnumerable().SelectMany(d => d._right).Concat(right.AsEnumerable().SelectMany(d => d._right)).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single);
1615
}
1716

1817
private Either(Maybe<L> left, Maybe<R> right)
@@ -21,35 +20,39 @@ private Either(Maybe<L> left, Maybe<R> right)
2120
_right = right;
2221
}
2322

24-
public static implicit operator Either<L, R>(L value) => MakeLeft(value);
25-
public static implicit operator Either<L, R>(R value) => MakeRight(value);
26-
27-
public static implicit operator Either<L, R>(Func<L> value) => LazyValue<L>.From(value);
23+
public static implicit operator Either<L, R>(R value) => Right(value);
2824
public static implicit operator Either<L, R>(Func<R> value) => LazyValue<R>.From(value);
25+
public static implicit operator Either<L, R>(LazyValue<R> value) => Right(value);
26+
public static implicit operator Either<L, R>(Either.EitherRight<R> value) => Right(value.Value);
2927

30-
public static implicit operator Either<L, R>(LazyValue<L> value) => MakeLeft(value);
31-
public static implicit operator Either<L, R>(LazyValue<R> value) => MakeRight(value);
32-
33-
public static implicit operator Either<L, R>(Either.EitherLeft<L> value) => MakeLeft(value.Value);
34-
public static implicit operator Either<L, R>(Either.EitherRight<R> value) => MakeRight(value.Value);
28+
public static implicit operator Either<L, R>(Func<L> value) => LazyValue<L>.From(value);
29+
public static implicit operator Either<L, R>(LazyValue<L> value) => Left(value);
30+
public static implicit operator Either<L, R>(L value) => Left(value);
31+
public static implicit operator Either<L, R>(Either.EitherLeft<L> value) => Left(value.Value);
3532

36-
public static Either<L, R> MakeLeft(Maybe<L> value) => new Either<L, R>(value, Maybe.None);
37-
public static Either<L, R> MakeRight(Maybe<R> value) => new Either<L, R>(Maybe.None, value);
33+
public static Either<L, R> Left(Maybe<L> value) => new Either<L, R>(value, Maybe.None);
34+
public static Either<L, R> Right(Maybe<R> value) => new Either<L, R>(Maybe.None, value);
3835

3936
public Maybe<L> Lhs() => _left;
4037
public Maybe<R> Rhs() => _right;
4138

4239
public LazyValue<V> Match<V>(Func<L, V> lhs, Func<R, V> rhs)
43-
=> _left.AsEnumerable().Select(lhs).Concat(_right.AsEnumerable().Select(rhs)).ToLazyValue();
40+
=> LazyValue.Defer(_left.AsEnumerable().Select(lhs).Concat(_right.AsEnumerable().Select(rhs)).Single);
4441

4542
public Maybe<V> Match<V>(Func<L, Maybe<V>> lhs, Func<R, Maybe<V>> rhs)
46-
=> _left.AsEnumerable().SelectMany(lhs).Concat(_right.AsEnumerable().SelectMany(rhs)).ToMaybe();
43+
=> Maybe.Defer(_left.AsEnumerable().SelectMany(lhs).Concat(_right.AsEnumerable().SelectMany(rhs)).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single);
4744

4845
public Either<VL, VR> MatchMany<VL, VR>(Func<L, Either<VL, VR>> lhs, Func<R, Either<VL, VR>> rhs)
49-
=> new Either<VL, VR>(_left.AsEnumerable().Select(lhs).ToMaybe(), _right.AsEnumerable().Select(rhs).ToMaybe());
46+
=> new Either<VL, VR>(
47+
Maybe.Defer(_left.AsEnumerable().Select(lhs).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single),
48+
Maybe.Defer(_right.AsEnumerable().Select(rhs).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single)
49+
);
5050

5151
public Either<VL, VR> MatchMap<VL, VR>(Func<L, VL> lhs, Func<R, VR> rhs)
52-
=> new Either<VL, VR>(_left.AsEnumerable().Select(lhs).ToMaybe(), _right.AsEnumerable().Select(rhs).ToMaybe());
52+
=> new Either<VL, VR>(
53+
Maybe.Defer(_left.AsEnumerable().Select(lhs).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single),
54+
Maybe.Defer(_right.AsEnumerable().Select(rhs).Select(Maybe.Just).DefaultIfEmpty(Maybe.None).Single)
55+
);
5356
}
5457

5558
public static class Either
@@ -62,12 +65,12 @@ public class EitherRight<T> { public LazyValue<T> Value { get; set; } }
6265

6366
public static EitherRight<T> Right<T>(LazyValue<T> rhs) => new EitherRight<T> { Value = rhs };
6467

65-
public static EitherLeft<T> Left<T>(Func<T> lhs) => new EitherLeft<T> { Value = LazyValue.From(lhs) };
68+
public static EitherLeft<T> Left<T>(Func<T> lhs) => new EitherLeft<T> { Value = LazyValue.Defer(lhs) };
6669

67-
public static EitherRight<T> Right<T>(Func<T> rhs) => new EitherRight<T> { Value = LazyValue.From(rhs) };
70+
public static EitherRight<T> Right<T>(Func<T> rhs) => new EitherRight<T> { Value = LazyValue.Defer(rhs) };
6871

69-
public static EitherLeft<T> Left<T>(T lhs) => new EitherLeft<T> { Value = LazyValue.From(lhs) };
72+
public static EitherLeft<T> Left<T>(T lhs) => new EitherLeft<T> { Value = LazyValue.Return(lhs) };
7073

71-
public static EitherRight<T> Right<T>(T rhs) => new EitherRight<T> { Value = LazyValue.From(rhs) };
74+
public static EitherRight<T> Right<T>(T rhs) => new EitherRight<T> { Value = LazyValue.Return(rhs) };
7275
}
7376
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System;
2+
using System.Linq;
3+
using System.Reactive.Linq;
4+
5+
namespace MorleyDev.Reactive.Monad.Extra
6+
{
7+
public static class EitherIO
8+
{
9+
public static MaybeIO<L> Lhs<L, R>(this IO<Either<L, R>> self) => self.SelectMany(s => s.Lhs());
10+
11+
public static MaybeIO<R> Rhs<L, R>(this IO<Either<L, R>> self) => self.SelectMany(s => s.Rhs());
12+
13+
public static IO<U> Match<U, L, R>(this IO<Either<L,R>> self, Func<L, U> lhs, Func<R, U> rhs)
14+
{
15+
return IO.From(self.AsObservable().SelectMany(either => either.Match(lhs, rhs)));
16+
}
17+
18+
public static IO<U> MatchMany<U, L, R>(this IO<Either<L, R>> self, Func<L, IO<U>> lhs, Func<R, IO<U>> rhs)
19+
{
20+
return IO.From(self.AsObservable().SelectMany(either => either.Match(lhs, rhs).Merge()));
21+
}
22+
23+
public static MaybeIO<U> MatchMany<U, L, R>(this IO<Either<L, R>> self, Func<L, MaybeIO<U>> lhs, Func<R, MaybeIO<U>> rhs)
24+
{
25+
return MaybeIO.From(self.AsObservable().SelectMany(either => either.Match(lhs, rhs).Merge()));
26+
}
27+
28+
public static IObservable<U> MatchMany<U, L, R>(this IO<Either<L, R>> self, Func<L, IObservable<U>> lhs, Func<R, IObservable<U>> rhs)
29+
{
30+
return self.AsObservable().SelectMany(either => either.Match(lhs, rhs).Merge());
31+
}
32+
33+
public static IO<Either<UL, UR>> MatchMap<UL, UR, L, R>(this IO<Either<L, R>> self, Func<L, UL> lhs, Func<R, UR> rhs)
34+
{
35+
return IO.From(self.AsObservable().Select(either => either.MatchMap(lhs, rhs)));
36+
}
37+
38+
public static IO<Either<UL, UR>> MatchMap<UL, UR, L, R>(this IO<Either<L, R>> self, Func<L, Either<UL, UR>> lhs, Func<R, Either<UL, UR>> rhs)
39+
{
40+
return IO.From(self.AsObservable().Select(either => either.MatchMany(lhs, rhs)));
41+
}
42+
43+
public static IO<Either<UL, UR>> MatchMap<UL, UR, L, R>(this IO<Either<L, R>> self, Func<L, Either.EitherLeft<UL>> lhs, Func<R, Either.EitherRight<UR>> rhs)
44+
{
45+
return IO.From(self.AsObservable().Select(either => either.MatchMany(v => (Either<UL, UR>)lhs(v), v => (Either<UL, UR>)rhs(v))));
46+
}
47+
48+
public static IO<Either<UL, UR>> MatchMap<UL, UR, L, R>(this IO<Either<L, R>> self, Func<L, Either.EitherRight<UR>> lhs, Func<R, Either.EitherLeft<UL>> rhs)
49+
{
50+
return IO.From(self.AsObservable().Select(either => either.MatchMany(v => (Either<UL, UR>)lhs(v), v => (Either<UL, UR>)rhs(v))));
51+
}
52+
53+
public static IO<Either<UL, UR>> MatchManyMap<UL, UR, L, R>(this IO<Either<L, R>> self, Func<L, IO<UL>> lhs, Func<R, IO<UR>> rhs)
54+
{
55+
return IO.From(
56+
self.AsObservable()
57+
.SelectMany(either => IO<Either<UL, UR>>.From(either
58+
.MatchMap(lhs, rhs)
59+
.Match(
60+
lhs2 => lhs2.Select(v => Either<UL, UR>.MakeLeft(Maybe.Just(v))),
61+
rhs2 => rhs2.Select(v => Either<UL,UR>.MakeRight(Maybe.Just(v)))
62+
)
63+
.ToObservable()
64+
.SelectMany(v => v)
65+
)
66+
)
67+
);
68+
}
69+
70+
public static IO<Either<UL, UR>> MatchManyMap<UL, UR, L, R>(this IO<Either<L, R>> self, Func<L, IO<Either<UL, UR>>> lhs, Func<R, IO<Either<UL, UR>>> rhs)
71+
{
72+
return IO.From(self.AsObservable().SelectMany(either => either.Match(lhs, rhs)).Merge());
73+
}
74+
}
75+
}

src/MorleyDev.Reactive.Monad/IO.cs

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,32 @@ namespace MorleyDev.Reactive.Monad
99
public static class IO
1010
{
1111
/// <summary>
12-
/// Wraps an IO Function into an synchronous IO
12+
/// Wraps an Asynchronous Action into an asynchronous IO
1313
/// </summary>
1414
/// <param name="unsafeIO"></param>
1515
/// <returns></returns>
16-
public static IO<T> From<T>(Func<T> unsafeIO) => From(Observable.Defer(() => Observable.Return(unsafeIO())));
16+
public static IO<T> Defer<T>(Func<Task<T>> unsafeIO) => IO<T>.From(Observable.Defer(() => unsafeIO().ToObservable()));
1717

1818
/// <summary>
19-
/// Wraps an IO Function into an synchronous IO
19+
/// Wraps an Asynchronous observable into an asynchronous IO
2020
/// </summary>
2121
/// <param name="unsafeIO"></param>
2222
/// <returns></returns>
23-
public static IO<Unit> From(Action unsafeIO) => From(() => { unsafeIO(); return Unit.Default; });
23+
public static IO<T> Defer<T>(Func<IObservable<T>> unsafeIO) => IO<T>.From(Observable.Defer(unsafeIO));
2424

2525
/// <summary>
26-
/// Wraps an Asynchronous Action into an asynchronous IO
26+
/// Runs a synchronous IO async via Task.Run and wraps the result in an IO
2727
/// </summary>
2828
/// <param name="unsafeIO"></param>
2929
/// <returns></returns>
30-
public static IO<T> From<T>(Func<Task<T>> unsafeIO) => From(Observable.Defer(() => unsafeIO().ToObservable()));
30+
public static IO<T> Run<T>(Func<T> unsafeIO) => IO<T>.From(Observable.Defer(() => Task.Run(unsafeIO).ToObservable()));
3131

3232
/// <summary>
33-
/// Wraps an Asynchronous observable into an asynchronous IO
33+
/// Runs a synchronous action via Task.Run that returns a void
3434
/// </summary>
35-
/// <param name="unsafeIO"></param>
35+
/// <param name="action"></param>
3636
/// <returns></returns>
37-
public static IO<T> From<T>(Func<IObservable<T>> unsafeIO) => From(Observable.Defer(unsafeIO));
37+
public static IO<Unit> Run(Action action) => IO<Unit>.From(Observable.Defer(() => Task.Run(action).ToObservable()));
3838

3939
/// <summary>
4040
/// Wraps an Asynchronous observable into an asynchronous IO
@@ -44,31 +44,12 @@ public static class IO
4444
public static IO<T> From<T>(IObservable<T> unsafeIO) => IO<T>.From(unsafeIO);
4545

4646
/// <summary>
47-
/// Runs a synchronous IO async via Task.Run and wraps the result in an IO
48-
/// </summary>
49-
/// <param name="unsafeIO"></param>
50-
/// <returns></returns>
51-
public static IO<T> Run<T>(Func<T> unsafeIO) => From(() => Task.Run(unsafeIO));
52-
53-
/// <summary>
54-
/// Runs a synchronous action via Task.Run that returns a void
47+
/// Returns an IO that contains the specified value
5548
/// </summary>
56-
/// <param name="action"></param>
57-
/// <returns></returns>
58-
public static IO<Unit> Run(Action action) => Run(() => {
59-
action();
60-
return Unit.Default;
61-
});
62-
63-
/// <summary>
64-
/// Runs a synchronous action via Task.Run that returns a void
65-
/// </summary>
66-
/// <param name="action"></param>
49+
/// <typeparam name="T"></typeparam>
50+
/// <param name="value"></param>
6751
/// <returns></returns>
68-
public static IO<Unit> From(Func<Task> action) => From(async () => {
69-
await action();
70-
return Unit.Default;
71-
});
52+
public static IO<T> Return<T>(T value) => IO<T>.From(Observable.Return(value));
7253
}
7354

7455
/// <summary>

src/MorleyDev.Reactive.Monad/LazyValue.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ namespace MorleyDev.Reactive.Monad
66
{
77
public static class LazyValue
88
{
9-
public static LazyValue<T> From<T>(Func<T> value) => LazyValue<T>.From(value);
9+
public static LazyValue<T> Defer<T>(Func<T> value) => LazyValue<T>.From(value);
1010

11-
public static LazyValue<T> From<T>(T value) => value;
11+
public static LazyValue<T> Return<T>(T value) => value;
1212
}
1313

1414
/// <summary>

0 commit comments

Comments
 (0)