Stream: beginners

Topic: Abilities


view this post on Zulip drew (May 22 2023 at 20:35):

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.

view this post on Zulip Brendan Hansknecht (May 22 2023 at 21:37):

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.

view this post on Zulip Ayaz Hafiz (May 22 2023 at 23:45):

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

view this post on Zulip Ayaz Hafiz (May 22 2023 at 23:46):

The syntax is subject to change soon, but only with regard to keyword names

view this post on Zulip drew (May 23 2023 at 00:53):

great, thanks

view this post on Zulip drew (May 23 2023 at 00:56):

yep these seem pretty straight forward

view this post on Zulip Luke Boswell (May 23 2023 at 07:05):

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.

view this post on Zulip Luke Boswell (May 23 2023 at 07:06):

Though I think the syntax has since been overtaken by more recent conversations, the ideas there may be helpful.

view this post on Zulip David Lysenko (Jun 28 2023 at 18:07):

Hello, I was wondering, is there any comprehensive guide on how abilities work? The section in the tutorial is missing.

view this post on Zulip Paul Kapustin (Sep 22 2023 at 13:47):

Hi, first I wanted to say thanks everyone, the language looks awesome so far, with so many great features and extremely well-thought choices!

view this post on Zulip Paul Kapustin (Sep 22 2023 at 13:47):

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?

view this post on Zulip Brendan Hansknecht (Sep 22 2023 at 14:28):

That is correct

view this post on Zulip Brendan Hansknecht (Sep 22 2023 at 14:28):

Type aliases are very light weight. They are essentially text replacement.

view this post on Zulip Brendan Hansknecht (Sep 22 2023 at 14:29):

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

view this post on Zulip Brendan Hansknecht (Sep 22 2023 at 14:31):

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.

view this post on Zulip Brendan Hansknecht (Sep 22 2023 at 14:31):

Opaque types are the only way to make a unique type that is allowed to be extended via abilities.

view this post on Zulip Paul Kapustin (Sep 22 2023 at 15:31):

Thanks a lot for the detailed explanation Brendan!

view this post on Zulip Richard Feldman (Sep 22 2023 at 23:21):

fun fact: the main reason for introducing opaque types to the language was specifically for abilities, to solve this problem :big_smile:

view this post on Zulip Narek Asadorian (Oct 18 2023 at 16:15):

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?

view this post on Zulip Richard Feldman (Oct 18 2023 at 16:15):

more like the former - they're closest to traits in Rust, except without associated types

view this post on Zulip Narek Asadorian (Oct 18 2023 at 16:17):

The similarity to Rust implies no higher kinds?

view this post on Zulip Richard Feldman (Oct 18 2023 at 16:17):

yeah

view this post on Zulip Artur Swiderski (Jan 27 2024 at 08:18):

there are no such abilities like math operators ? "* / + - " could be quite useful when crunching some weird numbers types

view this post on Zulip Artur Swiderski (Jan 27 2024 at 08:23):

and I think it is even required for high performance language. Or am I getting something wrong and I can do "+ - * /" on custom type?

view this post on Zulip Anton (Jan 27 2024 at 10:02):

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?

view this post on Zulip Artur Swiderski (Jan 27 2024 at 18:37):

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

view this post on Zulip Brendan Hansknecht (Jan 27 2024 at 18:51):

I am not, I just use it as a common example of cases where infix operators can be quite important

view this post on Zulip Brendan Hansknecht (Jan 27 2024 at 18:52):

Infix operators are never needed for performance, but they definitely can be a huge boon for readability and usability of some types.

view this post on Zulip Brendan Hansknecht (Jan 27 2024 at 18:55):

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

view this post on Zulip Artur Swiderski (Jan 28 2024 at 02:56):

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

view this post on Zulip misterdrgn (Jan 05 2025 at 18:51):

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.

view this post on Zulip Luke Boswell (Jan 05 2025 at 19:28):

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.

view this post on Zulip misterdrgn (Jan 05 2025 at 21:40):

@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.

view this post on Zulip Luke Boswell (Jan 05 2025 at 21:55):

No plans to remove ?, it's here for this reason :smiley:

view this post on Zulip Isaac Van Doren (Jan 05 2025 at 21:55):

The plan is to use ? for short circuiting in method call chains like in swift :smiley:

value.getSomethingThatMightBeMissing()?.doSomethingIfItWasThere()

view this post on Zulip misterdrgn (Jan 05 2025 at 21:56):

Got it. Overall this looks very exciting.

view this post on Zulip misterdrgn (Jan 05 2025 at 22:00):

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)?

view this post on Zulip Isaac Van Doren (Jan 05 2025 at 22:05):

The plan is to not support that because it makes it more difficult to tell where the methods you’re calling are coming from

view this post on Zulip Isaac Van Doren (Jan 05 2025 at 22:05):

There will most likely be a syntax allowing you to call functions defined outside of the module with a similar chaining syntax though

view this post on Zulip Anthony Bullard (Jan 05 2025 at 22:49):

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

view this post on Zulip Isaac Van Doren (Jan 05 2025 at 22:51):

Right good point, swift is probably expression level short circuiting

view this post on Zulip Anthony Bullard (Jan 05 2025 at 22:51):

That's the norm with ?. in all languages

view this post on Zulip Anthony Bullard (Jan 05 2025 at 22:52):

I wonder @Sam Mohr if it makes sense for us to keep try and ? and make ? expression level and keep try function level?

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

In rust it is function level

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

Does zig have function level as well?

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

Also, ! And ? used to be expression level and it was an explicit decision to change to function level.

view this post on Zulip Sam Mohr (Jan 05 2025 at 23:43):

I don't think its a problem at all for it to just be a function level thing

view this post on Zulip Sam Mohr (Jan 05 2025 at 23:43):

You can always wrap your expression in a closure


Last updated: Jul 06 2025 at 12:14 UTC