Last active
September 13, 2020 01:29
-
-
Save dcuccia/4029f1cddd7914dc1ae676d8c4af7866 to your computer and use it in GitHub Desktop.
This file contains 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
namespace DiscriminatedUnions | |
{ | |
using System.Collections.Generic; | |
using CartState = Union3<CartStateEmpty, CartStateActive, CartStatePaid>; | |
public class Union3<A, B, C> | |
{ | |
public Union3(A item) { Item = item; } | |
public Union3(B item) { Item = item; } | |
public Union3(C item) { Item = item; } | |
public dynamic Item { get; } | |
} | |
static class Program | |
{ | |
static void Main(string[] args) | |
{ | |
const decimal paidAmount = 12.34m; | |
// no real need for discriminated unions if process is deterministic | |
// just use the API to guard against unallowed transitions | |
var paid = new CartStateEmpty() | |
.AddProduct(Product.ProductX) | |
.AddProduct(Product.ProductY) | |
.Pay(paidAmount); | |
// but discriminated unions quite useful if there's branching | |
var empty = new CartState(new CartStateEmpty()); | |
var maybeAdded = empty.MaybeAddProduct(Product.ProductX); | |
var maybeAdded2 = maybeAdded.MaybeAddProduct(Product.ProductY); | |
var maybePaid = maybeAdded2.MaybePay(paidAmount); | |
} | |
public static CartState MaybeAddProduct(this CartState cartState, Product product) => cartState.Item switch | |
{ | |
CartStateEmpty => product.InStock ? new CartState( new CartStateActive(product) ) : cartState, | |
CartStateActive csa => new CartState(csa.AddProduct(product)), | |
_ => cartState | |
}; | |
public static CartState MaybePay(this CartState cartState, decimal amount) => cartState.Item switch | |
{ | |
CartStateActive csa => amount <= 1000 ? new CartState(csa.Pay(amount)) : cartState, | |
_ => cartState | |
}; | |
} | |
public class Product | |
{ | |
public static Product ProductX { get; } = new Product(); | |
public static Product ProductY { get; } = new Product(); | |
public bool InStock { get; } | |
} | |
class CartStateEmpty | |
{ | |
public CartStateActive AddProduct(Product product) => new CartStateActive(product); | |
} | |
class CartStateActive | |
{ | |
private IList<Product> _products; | |
public CartStateActive(Product product) | |
{ | |
_products = new List<Product>{ product }; | |
} | |
public CartStateActive AddProduct(Product product) | |
{ | |
_products.Add(product); | |
return this; | |
} | |
public CartStatePaid Pay(decimal amount) => new CartStatePaid(); | |
} | |
class CartStatePaid { } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment