Introduce Result<T,E>, an either monad

This commit is contained in:
ig 2023-09-14 14:25:05 +02:00
parent fc77a752b4
commit 3728ae747f
2 changed files with 104 additions and 9 deletions

104
csharp/Lib/Utils/Result.cs Normal file
View File

@ -0,0 +1,104 @@
namespace InnovEnergy.Lib.Utils;
// TODO: discriminated union
public abstract record Result<T>
{
public sealed record Success(T Value) : Result<T>;
public sealed record Failure(String Error) : Result<T>;
public Boolean IsError => this is Failure;
public Boolean IsOk => this is Success;
public static implicit operator Result<T>(T t) => new Success(t);
public static implicit operator Result<T>(String e) => new Failure(e);
}
public abstract record Result<T, E>
{
public sealed record Success(T Value) : Result<T, E>;
public sealed record Failure(E Error) : Result<T, E>;
public Boolean IsError => this is Failure;
public Boolean IsOk => this is Success;
public static implicit operator Result<T, E>(T t) => new Success(t);
public static implicit operator Result<T, E>(E e) => new Failure(e);
public R Map<R>(Func<T, R> onSuccess, Func<E, R> onFailure) => this switch
{
Success s => onSuccess(s.Value),
Failure f => onFailure(f.Error),
_ => throw new ArgumentOutOfRangeException()
};
public Result<R, E> OnSuccess<R>(Func<T, R> onOk) => this switch
{
Success s => onOk(s.Value),
Failure f => f.Error,
_ => throw new ArgumentOutOfRangeException()
};
public Result<T, R> OnFailure<R>(Func<E, R> onError) => this switch
{
Success s => s.Value,
Failure f => onError(f.Error),
_ => throw new ArgumentOutOfRangeException()
};
}
public static class Result
{
public static Result<T, Exception> Try<T>(Func<T> func)
{
try
{
return func();
}
catch (Exception e)
{
return e;
}
}
public static String? GetError<T>(this Result<T> r)
{
return r is Result<T>.Failure err
? err.Error
: null;
}
}
public static class ResultClass
{
public static T? GetValue<T>(this Result<T> r) where T : class
{
return r is Result<T>.Success ok
? ok.Value
: null;
}
public static E? GetError<T, E>(this Result<T, E> r) where E : class
{
return r is Result<T, E>.Failure err
? err.Error
: null;
}
}
public static class ResultStruct
{
public static T? GetValue<T>(this Result<T> r) where T : struct
{
return r is Result<T>.Success ok
? ok.Value
: null;
}
public static E? GetError<T, E>(this Result<T, E> r) where E : struct
{
return r is Result<T,E>.Failure err
? err.Error
: null;
}
}

View File

@ -1,9 +0,0 @@
namespace InnovEnergy.Lib.Utils.WIP;
// TODO: discriminated union
public abstract record Result
{
public sealed record Ok(Object Result) : Result;
public sealed record Error(String Message) : Result;
}