Stream: beginners

Topic: Identity function


view this post on Zulip Travis (Oct 10 2022 at 14:41):

is there a builtin identity function somewhere or should we just write \x -> x?

view this post on Zulip Travis (Oct 10 2022 at 14:43):

i'm often using this. is this the best way to express 'unwrap if ok'?

...
|> Result.try \x -> x

view this post on Zulip Ghislain (Oct 10 2022 at 15:00):

Do you have a bigger example?
Result.try has this definition :

try : Result a err, (a -> Result b err) -> Result b err

It doesn't look to fit with your example as the callback should return a Result

view this post on Zulip Travis (Oct 10 2022 at 15:03):

oh you're right. i was forgetting a Result. i need to use type annotations more. would have helped here.

view this post on Zulip Travis (Oct 10 2022 at 15:05):

so maybe i only thought i needed an identity function. is it even useful in roc? seems necessary in other functional langs.

view this post on Zulip Richard Feldman (Oct 10 2022 at 15:51):

my general view is that demand for an identity function is usually demand for a convenience operation in an API :big_smile:

view this post on Zulip Richard Feldman (Oct 10 2022 at 15:52):

e.g. in other languages I've often found myself using filterMap identity - but if there were a function (like keepOks in Roc) which directly did what I wanted, I'd use that instead!

view this post on Zulip Travis (Oct 10 2022 at 16:08):

seems good to me. was just curious. turns out i didn't really need it. will re-evaluate later on maybe after doing more of the advent problems (via zig platform btw ) :big_smile:

view this post on Zulip Travis (Oct 10 2022 at 16:10):

now that we have an at least partially working File.readBytes impl, i won't need to use multiline strings either

view this post on Zulip Travis (Oct 10 2022 at 17:30):

turns out i did need to use Result.try \x -> x here is the usage for more context. this is from my aoc 2021 day 2. without the last line it errors.

parseLine : Str -> Result Vec2 [InvalidNumStr]
parseLine = \line ->
    parsers = [
        \l -> parseDir l "up " {x: 0, y: -1},
        \l -> parseDir l "down " {x: 0, y: 1},
        \l -> parseDir l "forward " {x: 1, y: 0},
    ]

    List.walkUntil parsers (Err InvalidNumStr) \state, f ->
        when f line is
            Ok v -> Break (Ok v)
            Err _ -> Continue state
    |> Result.try \x -> x

view this post on Zulip Ghislain (Oct 10 2022 at 17:39):

Yes, my bad, I re-thought about your unwrap after posting my answer and understood what you could have written. :grimacing:

view this post on Zulip Ghislain (Oct 10 2022 at 17:41):

But, it looked a bit confusing to me to return a Result (Result a e) e. Here it looks like it's what returns your parseDir, or am I missing something?

view this post on Zulip Ghislain (Oct 10 2022 at 17:44):

maybe parseDir could be simplified to only return Result a e

view this post on Zulip Ghislain (Oct 10 2022 at 17:45):

Then you wouldn't have to unwrap if Ok

view this post on Zulip Ghislain (Oct 10 2022 at 17:48):

If you want to keep your parseDir signature, you could also have written:

when f line is
            Ok v -> Break v
            Err _ -> Continue state

Although it would still be confusing to keep an unknown Result after having unwrapped it with Ok v

view this post on Zulip Travis (Oct 10 2022 at 17:50):

yes i agree about the Result Result. that function needs some work. but its an improvement over what i started with. originally i was always doing all 3 parseDir calls and them List.keepOks followed by List.get 0 was very sad. so atleast this is an improvement.

view this post on Zulip Travis (Oct 10 2022 at 17:52):

i think the Break Ok v is needed because the state is a Result.

view this post on Zulip Travis (Oct 10 2022 at 17:52):

initially Err InvalidNumStr

view this post on Zulip Ghislain (Oct 10 2022 at 17:58):

:thinking: v should also be a Result ([Ok a, Err *]) so compatible with Err InvalidNumStr

view this post on Zulip Travis (Oct 10 2022 at 18:01):

yes i agree. but when i remove it i get this error:

This 2nd argument to try has an unexpected type:

24│      |> Result.try \x -> x
                       ^^^^^^^

The argument is an anonymous function of type:

    { x : Int Signed64, y : Int Signed64 } -> { x : Int Signed64,
    y : Int Signed64 }

But try needs its 2nd argument to be:

    { x : Int Signed64, y : Int Signed64 } ->
    Result b [InvalidNumStr]*

view this post on Zulip Travis (Oct 10 2022 at 18:02):

this was with Oct 8th build

view this post on Zulip Travis (Oct 10 2022 at 18:02):

it took me a few minutes to respond cause i had just installed Oct 10th build to check if my json parser lazy call was fixed

view this post on Zulip Travis (Oct 10 2022 at 18:03):

but that made my day2 code err with different errors

view this post on Zulip Ghislain (Oct 10 2022 at 18:06):

Yes, my point was to be able to remove the Result.try :sweat_smile:

view this post on Zulip Travis (Oct 11 2022 at 16:38):

i did end up removing the Result.try btw. here's how they ended up.

parseLine : Str -> Result Vec2 [InvalidNumStr]
parseLine = \line ->
    parsers = [
        \l -> parseDir l "up " {x: 0, y: -1},
        \l -> parseDir l "down " {x: 0, y: 1},
        \l -> parseDir l "forward " {x: 1, y: 0},
    ]

    List.walkUntil parsers (Err InvalidNumStr) \state, f ->
        when f line is
            Ok v -> Break (Ok v)
            Err _ -> Continue state

parseDir : Str, Str, Vec2 -> Result Vec2 [NotFound, InvalidNumStr]
parseDir = \line, startsWith, v ->
    Str.replaceFirst line startsWith ""
    |> Result.try \r -> Str.toI64 r
    |> Result.map \n -> vecMul v {x: n, y: n}

view this post on Zulip Travis (Oct 11 2022 at 16:39):

not too bad. i looked at your day 2 and like your solution better though which uses pattern matching

view this post on Zulip Travis (Oct 11 2022 at 16:42):

i wonder do you have any suggestions for cleaning this part up? would like to remove the last line somehow.

solve : Str -> { pos1 : Vec2, pos2 : Vec2 }
solve = \input ->
    vecs =
        Str.trim input
        |> Str.split "\n"
        |> List.map \line -> parseLine line
            # will overflow if reached - how to panic here or stop / return error?
            |> Result.withDefault {x:999999999999999, y:999999999999999}

view this post on Zulip Brendan Hansknecht (Oct 11 2022 at 16:43):

List.mapTry may help

view this post on Zulip Brendan Hansknecht (Oct 11 2022 at 16:43):

Instead of getting a list of results will give you a result of a list.

view this post on Zulip Travis (Oct 11 2022 at 16:46):

oh neat. will give it a 'try' :wink:

view this post on Zulip Travis (Oct 11 2022 at 17:15):

mapTry much better. now i can handle the error in main.

solve : Str -> Result { pos1 : Vec2, pos2 : Vec2 } [InvalidNumStr]
solve = \input ->
        Str.trim input
        |> Str.split "\n"
        |> List.mapTry \line -> parseLine line
        |> Result.map \vecs ->
        ...

Last updated: Jul 05 2025 at 12:14 UTC