Home > Software design >  How do I bind a method that returns an `Either` to a method that accepts an `Option` in Language-Ext
How do I bind a method that returns an `Either` to a method that accepts an `Option` in Language-Ext

Time:07-06

For simplicity, I'm presenting a use-case that isn't really realistic (eg role-checking could be done differently, etc), but I'm trying not to confuse the question, so please bear with me.

Suppose I want to write a method that accepts an int, and needs to...

  1. Check the authed used is in the appropriate role to make the request
  2. Check the Id corresponds to a customer in the database
  3. Check if the customer is active

If we get through all that lot, we return the customer, if not we return an error message.

If I use an Either-returning method for step 2, I can do something like this...

static Either<string, int> CheckUser(int n) {
  // Check the authed user is in the right role, etc
  // For simplicity, we'll decide based on the Id
  if (n < 0) {
    return "Not authorised to access customer data";
  }
  return n;
}

static Either<string, Customer> Exists(int n) =>
  // This would check the database
  n < 10 ? "Unknown customer" : new Customer(n, "Jim Spriggs");

static Either<string, Customer> IsActive(Customer c) {
  // This would check the customer, we just use a simple check on the Id for simplicity
  if (c.Id % 2 == 0) {
    return "Inactive";
  }
  return c;
}

record Customer(int Id, string Name);

I can then bind this together as follows...

CheckUser(36)
  .Bind(Exists)
  .Bind(IsActive)
  .Match(n => Console.WriteLine($"Success: {n}"), ex => Console.WriteLine($"Ex: {ex}"));

This works, but I can't help but feel that the Exists method should return an Option<Customer> rather than an Either<string, Customer>, eg (again simplified for clarity)...

static Option<Customer> Exists(int n) =>
    n < 10 ? Option<Customer>.None : new Customer(n, "Jim Spriggs");

However, I'm struggling to work out how to bind this between the other two methods. I thought that I could use Map to convert, but couldn't work out how to do this.

Anyone able to advise? Is it OK to use Either, or should I be using Option? If the latter, how do I fix my code?

Thanks

CodePudding user response:

Use ToEither:

[Fact]
public void Answer()
{
    var actual = CheckUser(36)
        .Bind(i => Exists(i).ToEither("Inactive"))
        .Bind(IsActive)
        .Match(n => $"Success: {n}", ex => $"Ex: {ex}");
    Assert.Equal("Ex: Inactive", actual);
}

The above test passes.

  • Related