Skip to content

Instantly share code, notes, and snippets.

@mollyporph
Last active March 17, 2016 16:16
Show Gist options
  • Save mollyporph/ab88b643aa6711016883 to your computer and use it in GitHub Desktop.
Save mollyporph/ab88b643aa6711016883 to your computer and use it in GitHub Desktop.
public class User
{
public string Name {get;set;}
public string Email{get;set;}
public string PhoneNumber{get;set;}
}
public class Program
{
public static void Main(string[] args){
User user = new User{Name ="Otto", Email="[email protected]", PhoneNumber ="+4613371337"
var res = Result.From(user)
.Then(CapitalizeName)
.Then(ValidateEmail)
.Then(SaveUser)
.Then(EnsureUserUnderstandsTheDocumentation)
if(res.HasException){
throw new Exception($"Validation failed for user {user.Name}",res.Exception);
}
}
}
}
//Only function that I cared to implement :P
public User CapitalizeName(User user)=> user.With(x => x.Name,x.Name.ToUpper());
//Bogus methods that should actually do something :P
public User ValidateEmail(User user) => user;
public User SaveUser(User user) => user;
//Obviously the user never understands the documentation
public User EnsureUserUnderstandsTheDocumentation(User user) => {throw new DivisionByZeroException();return user;}
public User NotifySubscribers(User user)=> user;
public static T With<T, P>(this T self, Expression<Func<T, P>> selector, P newValue)
{
var me = (MemberExpression)selector.Body;
var changedProp = (System.Reflection.PropertyInfo)me.Member;
var clone = Activator.CreateInstance<T>();
foreach (var prop in typeof(T).GetProperties())
prop.SetValue(clone, prop.GetValue(self));
changedProp.SetValue(clone, newValue);
return clone;
}
public class Result<T>
{
public bool HasException { get; private set; }
public Exception Exception { get; private set; }
public T Value { get; private set; }
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<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<U> Bind<T, U>(this Result<T> value, Func<T, Result<U>> k)
{
return (value.HasException)
? new Result<U>(value.Exception)
: k(value.Value);
}
public static Result<V> SelectMany<T, U, V>(this Result<T> value, Func<T, Result<U>> k, Func<T, U, V> m)
{
return value.Bind(t => k(t).Bind(u => m(t, u).Unit()));
}
}
public static class ResultExtensions
{
public static Result<U> Then<T, U>(this Result<T> value, Func<T, U> getValue)
{
return value.Bind(x => Result.Execute(() => getValue(x)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment