Open BADF00D opened 1 year ago
You can try the Bind ext method.
public record Result(string Name, int Age, Guid Id);
public class Parser
{
public OneOf<Result, Exception> Parse()
{
return GetName()
.Combind(GetAge())
.Combind2(GetId())
.MapT0(_ => new Result(_.Item1, _.Item2, _.Item3));
}
private OneOf<string, Exception> GetName() => "Value1";
private OneOf<int, Exception> GetAge() => 123;
private OneOf<Guid, Exception> GetId() => Guid.NewGuid();
}
public static class Ext
{
public static OneOf<(T1, T2), E> Combind<T1, T2, E>(this OneOf<T1, E> opt1, OneOf<T2, E> opt2)
=> opt1.Match(
t1 => opt2.Match(
t2 => OneOf<(T1, T2), E>.FromT0((t1, t2)),
e => e
),
e => e
);
public static OneOf<(T1, T2, T3), E> Combind2<T1, T2, T3, E>(this OneOf<(T1, T2), E> opt1, OneOf<T3, E> opt2)
=> opt1.Combind(opt2).MapT0(_ => (_.Item1.Item1, _.Item1.Item2, _.Item2));
}
Is there a better, more readable way to write the
Parse
method?
@BADF00D, enter the monad!
#r "nuget: OneOf, 3.0.243"
using OneOf;
public class Parser
{
public OneOf<Result, Exception> Parse() =>
GetName()
.AsBindable()
.Bind(name => new Result(name).AsBindable())
.Bind(result => GetAge().AsBindable().Bind(age => (result with { Age = age }).AsBindable()))
.Bind(result => GetId().AsBindable().Bind(id => (result with { Id = id }).AsBindable()))
.Result();
private OneOf<string, Exception> GetName() => "Value1";
private OneOf<int, Exception> GetAge() => 123;
private OneOf<Guid, Exception> GetId() => Guid.NewGuid();
}
// Monad
public class Maybe<TA> where TA: notnull
{
private OneOf<TA, Exception> value;
private Maybe(Exception ex) => value = ex;
public Maybe(TA someValue) => value = someValue;
public Maybe(OneOf<TA, Exception> value) => this.value = value;
public Maybe<TB> Bind<TB>(Func<TA, Maybe<TB>> f) where TB : notnull
=> value.Match(
taValue => f(taValue),
ex => Maybe<TB>.Exception(ex));
public static Maybe<TA> Exception(Exception ex) => new Maybe<TA>(ex);
public OneOf<TA, Exception> Result() => value;
}
// Extension methods
public static Maybe<TA> AsBindable<TA>(this TA value) where TA : notnull
=> new Maybe<TA>(value);
public static Maybe<TA> AsBindable<TA>(this OneOf<TA, Exception> oneof) where TA : notnull
=> new Maybe<TA>(oneof);
I'm new to this library and not quite sure if I use it the right way.
Imagine I want to write a little Parser, that returns a record of type
Result
. Each property is parsed by invoking a method that can parse this property or returns an exception. How would I write the Parse method, that collects the values from the methods?My current solution looks like the following:
Is there a better, more readable way to write the
Parse
method?