Created
September 26, 2016 09:08
-
-
Save mollyporph/71dae484359f3592696381c405cf3350 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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