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!
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"
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:
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"
This is exactly what I was looking for - thanks again, @Anton!
Awesome :)
Hristo has marked this topic as resolved.
Hristo has marked this topic as unresolved.
Hristo has marked this topic as resolved.
Last updated: Jul 06 2025 at 12:14 UTC