I'm coming from this video https://youtube.com/watch?v=VnPw9rk8FI8 where Richard talk about structural polymorphism and compares it to rust/Haskel style "classification based polymorphism". From what I understood, you just write Roc functions and the type system figures out the correct set of constraints to put on the arguments of the function. Without knowing the types / interfaces beforehand, how does an LSP figure out the type of something before you write the function? If I ask for a list of methods available on some variable, where do they come from?
ah, so the type checker does know what they all are! So let's say I define a new custom collection type and I give it associated functions of .len() and .concat(other)
as soon as LSP asks "what methods are available after this dot?" the type checker can tell the LSP of the type of the thing before the dot by looking it up in scope, and once you know the type you can just ask directly what methods were explicitly defined on that type
so that part of it is no different from, say, defining a method on a class and the LSP looking up the class of the thing in front of the dot
now if I'm doing this on a type that's not concrete, then it all depends on what constraints I've specified for it
for example if I'm writing a function and I put a type annotation on it that says the function's your is val -> U64 where [val.len : val -> U64, val.reverse : val -> val] then the LSP would autocomplete a dot after its argument to have the two methods of len and reverse because those are the 2 methods I said in the annotation it was required to have
So do you make those new custom collection types ad-hoc? or in the function signature themselves?
You need to know, before writing the function, that val needs to have the len and reverse methods, right?
either in the function signature or if you like you can make a named thing to reuse (like a type alias) if there are common ones you don't want to write over and over
no, not necessarily
for example if you'd already written arg.len() somewhere else in the function then the type checker would infer the len constraint for you, based on how you used that len method call
obviously it can't read your mind, so if you're writing the function completely from scratch it won't infer any constraints :smile:
I guess my underlying question is how do you plan on users of libraries to do "function / api surface discovery" I often find myself looking through the autocomplete methods looking for something that I want.
I think it will feel exactly like a normal language when it comes to autocomplete haha
Ok.
Also, a bit off topic from this question, but what other syntax did you explore before landing on the -> operator?
Why not just use .?
. is already used for chaining methods (functions associated with the type), the -> operator is to call a function defined locally
we talked about many different operators in zulip -- over various different threads. I feel like we threw around every possible symbol
Bringing up the autocomplete example again, do you plan on separating the lists of available functions/methods if I do x. vs x->? Or will the lists be combined and then the lsp replaces the . with a -> (or vice versa) if I selected a function when I had x.
I think this is the thread (it's very long)
Sorry, I wasn't able to find the threads. I'm new to zulip and searched for "->" but nothing came up
I'll look harder!
by default I assume we'll start with just . autocomplete and then see if in practice there's demand for ->
Luke Boswell said:
I think this is the thread (it's very long)
@Alex Ott can you see this thread?
I'm not sure if zulip let's you go back in time to older threads
Yes I can
Last updated: Nov 28 2025 at 12:16 UTC