Search code examples
c#language-ext

How to manage exceptions thrown from Result.Map delegate?


The code for LanguageExt.Common.Result.Map is as follow:

[Pure]
public Result<B> Map<B>(Func<A, B> f) =>
    IsFaulted 
        ? new Result<B>(Exception)
        : new Result<B>(f(Value));

How to manage the scenario where the Func f might throw an error too?

For example, let's say I have this:

public Result<string> DoFirst()
{
    return Result<string>("Good");
}

public Result<int> DoNext()
{
    var result = DoFirst();

    return result.Map<int>(_ =>
    {
        try
        {
            // Some unsafe code that will eventually
            // throw new InvalidOperationException();
            return 200;
        }
        catch(Exception ex)
        {
            // return Result<int>(ex); // Not allowed, must return an int
            // return ex; // Not allowed, must return an int
        }
    });
}

What happens if the Exception is not handled?

It seems like we are missing a FlatMap method or something like that, or May be I am not using the right Class.

######### ADDED #########

FlatMap could look like this:

[Pure]
public Result<B> FlatMap<B>(Func<A, Result<B>> f) =>
    IsFaulted 
        ? new Result<B>(Exception)
        : f(Value);

That would have solved my issue. Should I create a pull request?


Solution

  • You should use the Try<T> monad for that indeed

    public string DoFirst()
    {
      // Exceptions thrown here will be handled by the Try monad
      return "Good";
    }
    
    public int DoNext(string s)
    {  
      // Exceptions thrown here will be handled by the Try monad
      return 200;
    }
    
    public void Run() 
    {
      Prelude
        .Try(() => DoFirst())
        .Map(s => DoNext(s))
        .Match(
          i => { /* Do something with the result */ },
          ex => { /* Do something with the exception */ }
        );
    }
    

    Hope this helps a little 🙂