Problem Statement
The World Feet Organization (WFO) has tasked me with calculating the sum of shoe sizes provided by client applications. The data sent to my API might contain invalid shoe sizes, such as negative values. My goal is to use always-valid domain models, as it is common practice in domain-driven design.
I've always used Result classes that expose the success or failure object (similar to this question). If any object was not created with a valid state, the failure (Exception or Error) is returned, otherwise the success (the valid object) is returned.
Question
Using a functional programming paradigm with C# LanguageExt, how would one achieve this? The code below does the job, but the null
values used to skip the failure matching is just painful to look at. I just don't know how to access the values in any other way using this Result type.
Code Example
using LanguageExt.Common;
namespace ConsoleAppAlwaysValidFunctional;
public class Application
{
public Result<double> CalculateSumOfShoeSizes()
{
var footOne = Foot.Create(8.0);
var footTwo = Foot.Create(8.0);
var footThree = Foot.Create(18.0);
if (footOne.IsFaulted) // also, how do I pass the inner exception?
{
var e1 = footOne.Match(null, exception => exception);
return new Result<double>(e1); // like this?
}
if (footTwo.IsFaulted)
{
return new Result<double>(new Exception("Second foot is not valid"));
}
if (footThree.IsFaulted)
{
return new Result<double>(new Exception("Third foot is not valid"));
}
// all three objects are valid, extract the shoe sizes
var firstShoeSize = footOne.Match(success => success.ShoeSize, null);
var secondShoeSize = footTwo.Match(success => success.ShoeSize, null);
var thirdShoeSize = footThree.Match(success => success.ShoeSize, null);
var sum = firstShoeSize + secondShoeSize + thirdShoeSize;
return new Result<double>(sum);
}
}
public class Foot
{
public double ShoeSize { get; private set; }
private Foot(double shoeSize)
{
this.ShoeSize = shoeSize;
}
public static Result<Foot> Create(double shoeSize)
{
if (shoeSize < 0)
{
var exception = new Exception("Shoe size can't be negative");
return new Result<Foot>(exception);
}
var f = new Foot(8.0);
return new Result<Foot>(f);
}
}