Stream: ideas

Topic: Result.map_ok


view this post on Zulip Richard Feldman (Jan 14 2025 at 03:56):

Splitting this off from:

Sam Mohr said:

We do map and map_err, but map_ok and map_err would make more sense

view this post on Zulip Richard Feldman (Jan 14 2025 at 03:57):

I tried this out in the realworld app and it immediately made things clearer. Here's an example:

view this post on Zulip Richard Feldman (Jan 14 2025 at 03:57):

Before

params : Request -> List (Str, Str)
params = |req|
    req
    .path()
    .split_first("?")
    .map(.after)
    .with_default("")
    .split_on("&")
    .map(|param|
        when param.split_first("=") is
            Ok({ before, after }) -> (before, after)
            Err(NotFound) -> (param, "")
    )

view this post on Zulip Richard Feldman (Jan 14 2025 at 03:57):

After

params : Request -> List (Str, Str)
params = |req|
    req
    .path()
    .split_first("?")
    .map_ok(.after)
    .with_default("")
    .split_on("&")
    .map(|param|
        when param.split_first("=") is
            Ok({ before, after }) -> (before, after)
            Err(NotFound) -> (param, "")
    )

view this post on Zulip Richard Feldman (Jan 14 2025 at 03:58):

in the first version, there are two .map calls, one to Result.map and the other to List.map, but you have to look at the previous call to notice that split_first returns a Result and split_on returns a List

view this post on Zulip Richard Feldman (Jan 14 2025 at 03:59):

in the second version, every single function call after req.path() is uniquely identifiable without the module name, and req.path() has the variable name to tell you it's a request

view this post on Zulip Richard Feldman (Jan 14 2025 at 04:00):

I guess you don't know for sure that the map at the end is specifically List.map, but at least I can infer from the name that it's a collection (which is the relevant thing; I know it's being called N times instead of 0-1 times) as opposed to a Result

view this post on Zulip Richard Feldman (Jan 14 2025 at 04:09):

if we changed split_first and split_on to return tuples, and also did the .get_0() idea to replace .0 accessors, then this could become:

params : Request -> List (Str, Str)
params = |req|
    req
    .path()
    .split_first("?")
    .map_ok(.get_1())
    .with_default("")
    .split_on("&")
    .map(|param| param.split_first("=") ?? (param, ""))

view this post on Zulip Luke Boswell (Jan 14 2025 at 04:51):

Might be a bit soon, but I'm happy to make an Issue for this Result.map -> Result.map_ok and start including it in this round of breaking changes.

view this post on Zulip Sam Mohr (Jan 14 2025 at 04:52):

It feels good to break things, right? No need to keep stuff working, makes our job easier

view this post on Zulip Richard Feldman (Jan 14 2025 at 05:03):

works for me!

view this post on Zulip Richard Feldman (Jan 14 2025 at 05:03):

I'm definitely sold on trying this

view this post on Zulip Kasper Møller Andersen (Jan 14 2025 at 10:50):

I’m all for this. The difference to something like mapping a list is that here you’re only mapping data under certain conditions (if it’s Ok), which it’s good for the name to imply. As opposed to a list mapping, where you are mapping the data unconditionally.

view this post on Zulip Sam Mohr (Jan 14 2025 at 10:51):

A good explanation!

view this post on Zulip Chuck Daniels (Jan 14 2025 at 23:37):

Do you also want to change Result.map2 to Result.map2_ok (or similar)?

view this post on Zulip Luke Boswell (Jan 14 2025 at 23:40):

I feel like we don't want to change that. map2 feels fine because we're combining/chaining them. But I'm not sure on that.

view this post on Zulip Brendan Hansknecht (Jan 14 2025 at 23:42):

map2 probably should be renamed to chain or something similar

view this post on Zulip Brendan Hansknecht (Jan 14 2025 at 23:43):

That looks a lot nicer in record builder

view this post on Zulip Brendan Hansknecht (Jan 14 2025 at 23:43):

Though it is less searchable so :shrug:

view this post on Zulip Luke Boswell (Jan 14 2025 at 23:45):

How about Result.combine? -- I like chain too

view this post on Zulip Luke Boswell (Jan 14 2025 at 23:54):

What I like about chain is I think it tells me more about what it's doing and why I would use it. I feel like map2 is less friendly for anyone not already familiar with FP.

view this post on Zulip Brendan Hansknecht (Jan 15 2025 at 00:13):

A better name might also be some sort of join. Cause it takes 2 results and joins them into 1, but map2 is definitely a traditional name

view this post on Zulip Chuck Daniels (Jan 15 2025 at 00:47):

My concern with naming it something completely different than Result.map_ok would make it appear that it does something completely different when the only difference is that the given mapping function takes 2 args rather than only 1. Further, a name like chain (from my limited exposure to other FP langs/libs) seems more akin to bind/flat_map, but please do correct me if I'm off here.

view this post on Zulip Brendan Hansknecht (Jan 15 2025 at 00:50):

Yeah, chain really only looks good in record builder apis and is not really meaningful elsewhere.

view this post on Zulip Sam Mohr (Jan 15 2025 at 00:53):

Could call that out in the name and just call it Result.build

view this post on Zulip Chuck Daniels (Jan 15 2025 at 01:53):

How about Result.lift2?


Last updated: Jun 16 2026 at 16:19 UTC