Is there a good starting point for reading about the current state of abilities? I see the docs are "coming soon", but happy to read examples or the compiler source, i suppose.
They are functional. The builtins have a few examples. Not sure the best way to learn though.
In the builtins, Decode, Encode, Hash, and Dict all have examples of abilities both in definition and in use.
There are quite a few examples of source code files using abilities in these tests as well: https://github.com/roc-lang/roc/blob/main/crates/compiler/test_gen/src/gen_abilities.rs
The syntax is subject to change soon, but only with regard to keyword names
great, thanks
yep these seem pretty straight forward
If you come up with an example and feel like sharing, I think it would be really helpful to make it into an example. I have been trying to think of a small ability that would be interesting and show people how abilities language feature works. There is also Richard's design proposal, and some design notes in the repo which may be of assistance.
Though I think the syntax has since been overtaken by more recent conversations, the ideas there may be helpful.
Hello, I was wondering, is there any comprehensive guide on how abilities work? The section in the tutorial is missing.
Hi, first I wanted to say thanks everyone, the language looks awesome so far, with so many great features and extremely well-thought choices!
A question, do I understand it right that at the moment it is neither possible nor planned to allow implementing abilities for type aliases, or directly for records or tags? One can only implement an ability for a record or tag after first defining an opaque type wrapper, correct?
That is correct
Type aliases are very light weight. They are essentially text replacement.
Not that they work like that under the hood, but after all type checking is done, code typed via type alias is equivalent to code typed directly with the underlying type that the alias points to
As such, if you could add an ability to a type alias (or raw type definition), you would be adding that ability to all uses (even in totally unrelated code) of the type that the alias points to.
Opaque types are the only way to make a unique type that is allowed to be extended via abilities.
Thanks a lot for the detailed explanation Brendan!
fun fact: the main reason for introducing opaque types to the language was specifically for abilities, to solve this problem :big_smile:
I noticed in the Roc tutorial a mention of "abilities" with no content. Is this Roc's version of typeclasses? Or is it similar to abilities in a type+effect language like Unison?
more like the former - they're closest to traits in Rust, except without associated types
The similarity to Rust implies no higher kinds?
yeah
there are no such abilities like math operators ? "* / + - " could be quite useful when crunching some weird numbers types
and I think it is even required for high performance language. Or am I getting something wrong and I can do "+ - * /" on custom type?
there are no such abilities like math operators ? "* / + - "
No, you can read earlier discussions about it:
https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/customizing.20infix.20operators
https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/Numeric.20infix.20ops
I think it is even required for high performance language.
I don't think that is the case, can you explain your reasoning?
I think that someone may feel need to create complex numbers, and to craft generic function which operates on both real and complex numbers could be a plus, but I do not have strong opinion here. Btw I started to play with matrices I will continue since I have fun with it, but in the topic see that @Brendan Hansknecht is working on some kind of Matrix library?? am I correct?? If so will it be included in standard Roc? my own implementation while fun to play with will not do in long run. Having standard library for that, may be useful in the future
I am not, I just use it as a common example of cases where infix operators can be quite important
Infix operators are never needed for performance, but they definitely can be a huge boon for readability and usability of some types.
Anyway, current state is that there is no plan around custom infix operators. More discussion especially with concrete examples would be helpful in #ideas > customizing infix operators
as I said I have no strong opinion on that , it would be just useful to be able to create generic function, complex <-> real but I can easily live without it
I was initially excited, then confused about Abilities. I like them because they sound a lot like protocols/interfaces/traits in other modern languages. But in fact they're restricted to be usable only with opaque types, and thus primarily for building packages that other people will use (which is where opaque types make the most sense). The reason, I think, is that you don't need Abilities if you aren't using opaque types--you can rely on row polymorphism to achieve most of the same ends.
Is all of that correct? Am I confused about some things? I appreciate the help.
EDIT: Reading over previous posts about abilities, it sounds like opaque types were created for abilities, rather than abilities being created for opaque types. Still, I think the reasoning stands. If you want a function to work for any record that has certain characteristics, you use row polymorphism. If you want it to work for multiple data structures that may have entirely distinct implementations, you use opaque types and abilities. You lose out in cases where you want something ability-like for a record type, such as customizing its inspector string. So in that respect, Roc is less maleable than some programming languages, which appears to be an intentional design choice.
There has been a lot of design discussion and iteration recently.
See https://github.com/roc-lang/roc/issues/7458
Abilities look like they'll be replaced with static dispatch. So implicit interfaces, which will be mich simpler and nicer to use I think.
@Luke Boswell Oh, interesting. This approach to static dispatch sounds really similar to Lean4. Except that you can’t use . to chain function calls in Lean4 because it doesn’t support passing comma-separated arguments in parentheses.
I like . chaining in languages like Swift, but I think it depends critically on having ?. syntax to short-circuit the chain when an optional value is nil. I heard there was talk of removing ? from Roc, so I’m curious how that will turn out.
EDIT: Reading more of the proposal, I see how .try could be used in this case, though it does require nesting. Overall, this proposal subs very cool and definitely increases my excitement about the language. I assume all this will take some time, since it’s a new issue.
No plans to remove ?
, it's here for this reason :smiley:
The plan is to use ?
for short circuiting in method call chains like in swift :smiley:
value.getSomethingThatMightBeMissing()?.doSomethingIfItWasThere()
Got it. Overall this looks very exciting.
Oh, here’s a question. Will there be a way to add methods to an existing module, like you can do with Swift types (or in ocaml, lean4, etc)?
The plan is to not support that because it makes it more difficult to tell where the methods you’re calling are coming from
There will most likely be a syntax allowing you to call functions defined outside of the module with a similar chaining syntax though
The chaining syntax is a little ... surprising in it's behavior. This is NOT an expression-level short circuit. This short circuits the entire rest of the function
Right good point, swift is probably expression level short circuiting
That's the norm with ?.
in all languages
I wonder @Sam Mohr if it makes sense for us to keep try
and ?
and make ?
expression level and keep try
function level?
In rust it is function level
Does zig have function level as well?
Also, ! And ? used to be expression level and it was an explicit decision to change to function level.
I don't think its a problem at all for it to just be a function level thing
You can always wrap your expression in a closure
Last updated: Jul 06 2025 at 12:14 UTC