Refactored Option<T> to have opertator lifting and removed ref struct for now.
All checks were successful
Build NuGet / build (push) Successful in 1m43s
All checks were successful
Build NuGet / build (push) Successful in 1m43s
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace SJK.Functional;
|
||||
|
||||
public interface IEither<TLeft, TRight>
|
||||
@@ -12,3 +14,140 @@ public interface IEither<TLeft, TRight>
|
||||
bool IsRight();
|
||||
bool IsLeft() => !IsRight();
|
||||
}
|
||||
// public class test
|
||||
// {
|
||||
// public static void Main()
|
||||
// {
|
||||
// var res = TestEither();
|
||||
// if (res.Ok)
|
||||
// {
|
||||
|
||||
// }
|
||||
// res.Match(success => Option.Some(success), error => Option.None<int>());
|
||||
// }
|
||||
// public static Result<int,bool> TestEither()
|
||||
// {
|
||||
// return new Result<int,bool>();
|
||||
// }
|
||||
// }
|
||||
public struct Either<TLeft,TRight>
|
||||
{
|
||||
private TLeft? _left;
|
||||
private TRight? _right;
|
||||
[MemberNotNullWhen(true,nameof(_left)), MemberNotNullWhen(false,nameof(_right))]
|
||||
public bool IsLeft {get;init;}
|
||||
public bool IsRight => !IsLeft;
|
||||
private Either(TLeft? _left, TRight? right, bool isLeft)
|
||||
{
|
||||
this._left = _left;
|
||||
_right = right;
|
||||
IsLeft = isLeft;
|
||||
// Union<int,long,double>.Create(5,union =>
|
||||
// {
|
||||
// union.Set(5.0);
|
||||
// var s = union.Match(
|
||||
// i => i.ToString(),
|
||||
// i => i.ToString(),
|
||||
// i => i.ToString()
|
||||
// );
|
||||
// });
|
||||
}
|
||||
public (Option<TLeft> left, Option<TRight> right) Deconstruct() => (_left,_right);
|
||||
[MemberNotNullWhen(true,nameof(_right)),MemberNotNullWhen(false,nameof(_left))]
|
||||
public TLeft Reduce(Func<TRight,TLeft> mapping) => IsLeft?_left:mapping(_right);
|
||||
public TResult Match<TResult>(Func<TLeft,TResult> left, Func<TRight,TResult> right) => IsLeft ? left(_left) : right(_right);
|
||||
Either<TNewLeft, TRight> MapLeft<TNewLeft>(Func<TLeft, TNewLeft> mapping) => IsLeft? Either<TNewLeft,TRight>.Left(mapping(_left)) :Either<TNewLeft,TRight>.Right(_right);
|
||||
Either<TLeft, TNewRight> MapRight<TNewRight>(Func<TRight, TNewRight> mapping) => IsLeft? Either<TLeft,TNewRight>.Left(_left) :Either<TLeft,TNewRight>.Right(mapping(_right));
|
||||
public static Either<TLeft,TRight> Left(TLeft left) => new(left,default,true);
|
||||
public static Either<TLeft,TRight> Right(TRight right) => new(default,right,false);
|
||||
}
|
||||
|
||||
public ref struct Union<T,T2,T3> where T : unmanaged where T2 : unmanaged where T3 : unmanaged
|
||||
{
|
||||
private byte _type;
|
||||
private Span<byte> _data;
|
||||
public static unsafe int SizeInBytes => System.Math.Max(System.Math.Max(sizeof(T),sizeof(T2)),sizeof(T3));
|
||||
public Union(Span<byte> buffer)
|
||||
{
|
||||
_data = buffer;
|
||||
}
|
||||
public Union()
|
||||
{
|
||||
_data = new byte[SizeInBytes];
|
||||
}
|
||||
public static void Create(T value,Action<Union<T,T2,T3>> action)
|
||||
{
|
||||
Span<byte> span = stackalloc byte[SizeInBytes];
|
||||
var union = new Union<T,T2,T3>(span);
|
||||
union.Set(value);
|
||||
action(union);
|
||||
}
|
||||
public static void Create(T2 value,Action<Union<T,T2,T3>> action)
|
||||
{
|
||||
Span<byte> span = stackalloc byte[SizeInBytes];
|
||||
var union = new Union<T,T2,T3>(span);
|
||||
union.Set(value);
|
||||
action(union);
|
||||
}
|
||||
public static void Create(T3 value,Action<Union<T,T2,T3>> action)
|
||||
{
|
||||
Span<byte> span = stackalloc byte[SizeInBytes];
|
||||
var union = new Union<T,T2,T3>(span);
|
||||
union.Set(value);
|
||||
action(union);
|
||||
}
|
||||
public void Set(in T value)
|
||||
{
|
||||
System.Runtime.InteropServices.MemoryMarshal.Write(_data, value);
|
||||
_type = 1;
|
||||
}
|
||||
|
||||
public void Set(in T2 value)
|
||||
{
|
||||
System.Runtime.InteropServices.MemoryMarshal.Write(_data, value);
|
||||
_type = 2;
|
||||
}
|
||||
|
||||
public void Set(in T3 value)
|
||||
{
|
||||
System.Runtime.InteropServices.MemoryMarshal.Write(_data, value);
|
||||
_type = 3;
|
||||
}
|
||||
public void Match(
|
||||
Action<T> t,
|
||||
Action<T2> t2,
|
||||
Action<T3> t3
|
||||
)
|
||||
{
|
||||
switch(_type)
|
||||
{
|
||||
case 1:
|
||||
t(As<T>());
|
||||
break;
|
||||
case 2:
|
||||
t2(As<T2>());
|
||||
break;
|
||||
case 3:
|
||||
t3(As<T3>());
|
||||
break;
|
||||
};
|
||||
}
|
||||
public TResult Match<TResult>(
|
||||
Func<T,TResult> t,
|
||||
Func<T2,TResult> t2,
|
||||
Func<T3,TResult> t3
|
||||
) => _type switch
|
||||
{
|
||||
1=>t(As<T>()),
|
||||
2=>t2(As<T2>()),
|
||||
3=>t3(As<T3>()),
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
|
||||
public ref T As<T>()
|
||||
where T : unmanaged
|
||||
{
|
||||
return ref System.Runtime.InteropServices.MemoryMarshal.Cast<byte, T>(_data)[0];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user