Expressing typical map() function
My googling has come up dry, so I thought I'd ask here: is there any implementation of the typical map() you would find in other implementations of the result monad? I'm trying to get something closer to LanguageExt's implementation without the apparent expectation that it's being used in LINQ syntax. (Really, all of this is to try to emulate Rust's first-class support for the concept.)
Here's an extension method that gets at the syntax I'm looking for, but I can't shake the feeling that I'm working around something that's already available in FluentResults:
public static Result<TNew> Map<TNew, TOld>(this Result<TOld> @this, Func<TOld, Result<TNew>> func)
{
if (@this.IsSuccess)
{
return func(@this.Value);
}
return new Result<TNew>()
.WithSuccesses(@this.Successes)
.WithErrors(@this.Errors);
}
used as
Result<Foo> GetFoo() { ... }
Result<Bar> GetBar(Foo foo) { ... }
Result<Bar> result = GetFoo().Map(x => GetBar(x));
I can understand if it's not FluentResult's primary intention to be used as a result monad, but it seems it's very close to having this capability assuming it doesn't have the capability already.
Hi, having a .Map doesn't make an object to be a monad, only a functor. I think the .Map can be a handy alias of .ToResult. @altmann what do you think?
Consider this code:
Result<int> ri = Result.Ok(1);
Result<string> rs1 = ri.ToResult(static i => i.ToString());
Result<string> rs2 = ri.Map(static i => i.ToString());
Perhaps I'm not doing something correctly -- I don't think ToResult has the behavior I need.

Notice how the second ToResult returns a Result<Result<T>> instead of just a Result<T>.
However, with Map:

Ok, .Map functions normally map the value of the structure into a new value. A function called .Bind or .FlatMap, or .Then or .AndThen.
If you come from Haskell, .Map is like fmap and the others are like >>=. Rust equivalent is .and_then (Option type).
I would suggest to call it .FlatMap. Maybe it can implement IEnumerable and .SelectMany (losing its errors).
and_then is indeed what I'm talking about, but in the Result type 😄 though this implementation of Result<T> doesn't map cleanly to Rust's Result<T,E>, so perhaps you just mean that this implementation is closer to Option<T>.
Yeah, in retrospect, Map wasn't the best name for my extension method. I was copying typescript-monads' syntax just from familiarity with another project that uses it, but thanks for pointing out the discrepancy!
Hi guys!
First: ToResult(...) is not what you want. See https://github.com/altmann/FluentResults#converting for details - ToResult() is for converting from Result<T> to Result or vice versa.
Second: This functional magic was already discussed in some issues in the past (#132, #108). Please read it. Summary: I don't want to introduce such a complexity in the FluentResults library. If you need it then please implement it in your own project and please let us know in some months how was the dev experience.
I have already 2 projects using the .Bind method. Before this, we were treating the Result in similar way as golang treat errors, it was too pattern-y imperative handling of errors.
The .Bind method will bring OOP style, rather than structural/procedural. I wouldn't call it "functional magic". Because it is a technique of Category Theory, popular in FP, and yet not part of it. And we are going to express it in OOP (kind of smalltalk style, methods over statements and message passing).
I see @vermiculus can also benefit.
I can submit an implementation if you agree.
How many methods do you think you will add? Can you write down the signatures please so that I get the big picture. Thanks
public Result<TNewValue> Bind<TNewValue>(Func<TValue, Result<TNewValue>> valueConverter)
The name is debatable, since there is the ToResult<TNewValue> method, maybe BindResult or ToFlatResult.
The idea is simple, be able to call functions that take a T with a Result<T>.
Additionally, if agreed, the BindAsync can be implemented for convenience.
Maybe an alias for ToResult<T> as Map<T> ?
Please create a pr so that I get the idea. MVP style - let the ToResult(..) stable and don't create a Map alias for them.
Sorry for the delay. I reviewed the pr and merged it into the master. I will wait for a pr of another issue - by the end of the week I will publish a new version of FluentResults
New package is out https://www.nuget.org/packages/FluentResults/3.12.0
Thanks for your time inventstment.
Hi all
So, currently there is .Bind() and .Map() exists.
What is the difference between both ?