Skip to content

Instantly share code, notes, and snippets.

@mollyporph
Created September 26, 2016 09:08
Show Gist options
  • Save mollyporph/71dae484359f3592696381c405cf3350 to your computer and use it in GitHub Desktop.
Save mollyporph/71dae484359f3592696381c405cf3350 to your computer and use it in GitHub Desktop.
public class Result<T>
{
public bool HasException { get; }
public Exception Exception { get; }
public T Value { get; }
public Result(T value)
{
HasException = false;
Value = value;
}
public Result(Exception exception)
{
HasException = true;
Exception = exception;
}
public Result(Func<T> getValue)
{
try
{
Value = getValue();
HasException = false;
}
catch (Exception exc)
{
Exception = exc;
HasException = true;
}
}
public override string ToString()
=> HasException ? Exception.GetType().Name : (Value != null ? Value.ToString() : "null");
}
public static class Result
{
public static Result<T> From<T>(T value)
{
return value.Unit();
}
public static Result<T> Execute<U0, T>(Func<U0, T> fn, U0 u0)
{
return Execute(() => fn(u0));
}
public static Result<T> Execute<T>(Func<T> getValue)
{
return getValue.Unit();
}
}
public static class ResultMonadExtensions
{
public static Result<T> Unit<T>(this T value)
{
return new Result<T>(value);
}
public static Result<T> Unit<T>(this Func<T> getValue)
{
return new Result<T>(getValue);
}
public static Result<TU> Bind<T, TU>(this Result<T> value, Func<T, Result<TU>> k)
{
return (value.HasException)
? new Result<TU>(value.Exception)
: k(value.Value);
}
}
public static class ResultExtensions
{
public static Result<T2> Then<T, T2>(this Result<T> value, Func<T, T2> getValue)
{
return value.Bind(x => Result.Execute(() => getValue(x)));
}
public static Result<T> ThenEnsure<T>(this Result<T> value, Func<T, bool> validate)
{
if (value.HasException)
return new Result<T>(value.Exception);
return validate(value.Value)
? new Result<T>(value.Value)
: new Result<T>(new ValidationException($"Validation failed on {validate.Method.Name}", nameof(value)));
}
public static Result<T2> ThenEither<T, T2>(this Result<T> value, Func<T, bool> conditional, Func<Result<T>, Result<T2>> onTrue, Func<Result<T>, Result<T2>> onFalse)
{
try {
var isTrue = conditional(value.Value);
return value.Bind(x => isTrue ? onTrue(value) : onFalse(value));
}
catch(Exception e)
{
return new Result<T2>(e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment