Skip to content

Instantly share code, notes, and snippets.

@AlbertoMonteiro
Created October 25, 2016 00:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlbertoMonteiro/6aa46940d431ef8ff187723ac734853a to your computer and use it in GitHub Desktop.
Save AlbertoMonteiro/6aa46940d431ef8ff187723ac734853a to your computer and use it in GitHub Desktop.
Discriminated Unions
using System;
using static EspecialTry.Helpers;
namespace EspecialTry
{
public class Try<TFailure, TSuccess>
{
internal TFailure Failure { get; }
internal TSuccess Success { get; }
public bool IsFailure { get; }
public bool IsSucess => !IsFailure;
internal Try(TFailure failure)
{
IsFailure = true;
Failure = failure;
Success = default(TSuccess);
}
internal Try(TSuccess success)
{
IsFailure = false;
Failure = default(TFailure);
Success = success;
}
public static implicit operator Try<TFailure, TSuccess>(TFailure failure)
=> new Try<TFailure, TSuccess>(failure);
public static implicit operator Try<TFailure, TSuccess>(TSuccess success)
=> new Try<TFailure, TSuccess>(success);
public TResult Match<TResult>(Func<TFailure, TResult> failure, Func<TSuccess, TResult> success) => IsFailure ? failure(Failure) : success(Success);
public Unit Match(Action<TFailure> failure, Action<TSuccess> success)
=> Match(ToFunc(failure), ToFunc(success));
public Try<TFailure, TResult> Match<TResult>(Action<TFailure> failure, Func<TSuccess, TResult> success)
=> IsFailure ? new Try<TFailure, TResult>(Failure) : success(Success);
public Try<TFailure, TResult> Match<TResult>(Action<TFailure> failure, Func<TSuccess, Try<TFailure, TResult>> success)
=> IsFailure ? new Try<TFailure, TResult>(Failure) : success(Success);
}
public struct Unit
{ }
public static partial class Helpers
{
private static readonly Unit unit = new Unit();
public static Unit Unit() => unit;
public static Func<T, Unit> ToFunc<T>(Action<T> action) => o =>
{
action(o);
return Unit();
};
public static Try<Exception, T> AsTry<T>(this T exception)
=> new Try<Exception, T>(exception);
}
}
using System;
using static System.Console;
namespace EspecialTry
{
class Program
{
static void Main(string[] args)
{
Divide(4, 2)
.Match(failure: e => WriteLine(e.Message),
success: MultiplicaPorDez)
.Match(failure: e => WriteLine(e.Message),
success: value => value + 1)
.Match(failure: e => WriteLine(e.Message),
success: WriteLine);
Divide(4, 0)
.Match(failure: e => WriteLine(e.Message),
success: MultiplicaPorDez)
.Match(failure: e => WriteLine(e.Message),
success: value => WriteLine(value));
Divide(4, 1)
.Match(failure: e => WriteLine(e.Message),
success: value =>
{
if (value == 4)
return new Exception("Hi");
return 1.AsTry();
})
.Match(failure: e => WriteLine(e.Message),
success: value => WriteLine(value));
}
private static double MultiplicaPorDez(double value)
=> value * 10;
public static Try<Exception, double> Divide(double a, double b)
{
if (Math.Abs(b) < 0.0001) return new DivideByZeroException();
return a / b;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment