I'm trying to grok how to deal with functions that turn one "Either" into many "Either"s and how you then merge those back into a single stream.
The following turns one string into many numbers, squaring each and ignoring any errors. Given "1,2,Foo,4" it writes out 1,4,16.
It works but I don't understand why Bind(SafeSplit) returns an EitherData which has a Right property I need to dereference.
private static void ValidationPipelineVersion()
{
var result = Right<Exception, string>("1,2,Foo,4")
.Bind(SafeSplit)
.Bind(numStrs => numStrs.Right.Select(SafeParse))
.Rights() // ignore exceptions for now
.Map(num => num * num) // Squared
.Iter(num => WriteLine(num));
}
private static Either<Exception,string[]> SafeSplit(string str)
{
try
{
return str.Split(",");
}
catch (Exception e)
{
return e;
}
}
private static Either<Exception,int> SafeParse(string str)
{
try
{
return int.Parse(str);
}
catch (Exception e)
{
return e;
}
}
You don't have to (in fact, I'd advise against it), but it compiles because the LanguageExt library comes with a
Bindoverload with this signature:and since
Either<L, R>implementsIEnumerable<EitherData<L, R>>the code in the OP compiles.The reason it's not advisable is because the
Rightproperty is partial or unsafe. It works as long as theEitherobject is aRightvalue, but the whole point of the type is that you rarely know whether or not that's the case.Here's an alternative expression that may not look much simpler, but at least is safer:
Instead of trying to get the value out of the monad, it keeps the outer
Eithercontainer and performs all actions inside of it.