Stream: beginners

Topic: ✔ Is it possible to define tag-specific functions?


view this post on Zulip Hristo (Mar 19 2024 at 09:37):

The following is an adaptation of the Docs example on defining a new ability.

Is there an idiomatic Roc way, whereby I could effectively achieve something similar to the following (which obviously isn't valid Roc)? I'm trying to delegate tag-specific behaviour to separate functions, as the number of tags in my use-case is relatively large, and the functions themselves aren't short enough to enable good readability if they're all inlined within a single when...is.
Essentially, this is a question which doesn't have to do with the abilities example per se, but I'd like to utilise the described functionality in a custom ability context.
Please, note that I'd like to be able to have access to the color inside each tag-specific function (i.e., inside inspectGreen etc.), without having to pattern-match there as well.

CustomInspect implements
    inspectMe : val, Str -> Str where val implements CustomInspect

inspect : val, Str -> Str where val implements CustomInspect
inspect = \val, suffix -> inspectMe val suffix

Color := [Red, Green, Blue]
    implements [
        Eq,
        CustomInspect {
            inspectMe: inspectColor,
        },
    ]

inspectRed : Color Red a, Str -> Str
inspectRed = \@Color _, suffix ->
    "Red : $(suffix)"

inspectGreen: Color Green a, Str -> Str
inspectGreen = \@Color _, suffix ->
    "Green : $(suffix)"

inspectBlue: Color Blue a, Str -> Str
inspectBlue = \@Color _, suffix ->
    "Blue : $(suffix)"

inspectColor : Color, Str -> Str
inspectColor = \@Color color, suffix ->
    when color is
        Red -> inspectRed color suffix
        Green -> inspectGreen color suffix
        Blue -> inspectBlue color suffix

expect
    [@Color Red, @Color Green, @Color Blue]
    |> List.map inspect "10"
    |> Str.joinWith ","
    |> Bool.isEq "Red : 10,Green : 10,Blue : 10"

Thank you!

view this post on Zulip Anton (Mar 19 2024 at 10:18):

This modified version works, is this what you wanted?

CustomInspect implements
    inspectMe : val, Str -> Str where val implements CustomInspect

inspect : val, Str -> Str where val implements CustomInspect
inspect = \val, suffix -> inspectMe val suffix

Color := [Red, Green, Blue]
    implements [
        Eq,
        CustomInspect {
            inspectMe: inspectColor,
        },
    ]

inspectRed : Str -> Str
inspectRed = \suffix ->
    "Red : $(suffix)"

inspectGreen: Str -> Str
inspectGreen = \suffix ->
    "Green : $(suffix)"

inspectBlue: Str -> Str
inspectBlue = \suffix ->
    "Blue : $(suffix)"

inspectColor : Color, Str -> Str
inspectColor = \@Color color, suffix ->
    when color is
        Red -> inspectRed suffix
        Green -> inspectGreen suffix
        Blue -> inspectBlue suffix

expect
    [@Color Red, @Color Green, @Color Blue]
    |> List.map (\elt -> inspect elt "10")
    |> Str.joinWith ","
    |> Bool.isEq "Red : 10,Green : 10,Blue : 10"

view this post on Zulip Hristo (Mar 19 2024 at 10:25):

Thanks, @Anton! Apologies for my not having been clear enough in my original post (I'll update it now accordingly).

I'd like to be able to have access to the color inside each tag-specific function (i.e., inside inspectGreen etc.), without having to pattern-match there as well.

I hope this manages to clarify matters further :pray:

view this post on Zulip Anton (Mar 19 2024 at 10:50):

No problem, how about this:

CustomInspect implements
    inspectMe : val, Str -> Str where val implements CustomInspect

inspect : val, Str -> Str where val implements CustomInspect
inspect = \val, suffix -> inspectMe val suffix

Color := [Red, Green, Blue]
    implements [
        Eq,
        CustomInspect {
            inspectMe: inspectColor,
        },
    ]

inspectRed : [Red], Str -> Str
inspectRed = \red, suffix ->
    "Red : $(suffix)"

inspectGreen: [Green], Str -> Str
inspectGreen = \green, suffix ->
    "Green : $(suffix)"

inspectBlue: [Blue], Str -> Str
inspectBlue = \blue, suffix ->
    "Blue : $(suffix)"

inspectColor : Color, Str -> Str
inspectColor = \@Color color, suffix ->
    when color is
        Red -> inspectRed Red suffix
        Green -> inspectGreen Green suffix
        Blue -> inspectBlue Blue suffix

expect
    [@Color Red, @Color Green, @Color Blue]
    |> List.map (\elt -> inspect elt "10")
    |> Str.joinWith ","
    |> Bool.isEq "Red : 10,Green : 10,Blue : 10"

view this post on Zulip Hristo (Mar 19 2024 at 10:53):

This is exactly what I was looking for - thanks again, @Anton!

view this post on Zulip Anton (Mar 19 2024 at 10:53):

Awesome :)

view this post on Zulip Notification Bot (Mar 19 2024 at 10:54):

Hristo has marked this topic as resolved.

view this post on Zulip Notification Bot (Mar 19 2024 at 20:45):

Hristo has marked this topic as unresolved.

view this post on Zulip Notification Bot (Mar 19 2024 at 20:47):

Hristo has marked this topic as resolved.


Last updated: Jul 06 2025 at 12:14 UTC