* e.g in List * has caused a good bit of confusion throughout the years.
After trying to come up with the best explanation for its quirks I wondered if we could get rid of it.
Especially because it is just syntax sugar, e.g. List * -> List * becomes List a -> List b.
For clarification; * is a type variable whose name appears nowhere else in this type annotation.
From my current understanding:
* is that an experienced Roc user can immediately see that this is a type variable that occurs nowhere else in the annotation and thus also implements no abilities.List * -> List *.The drawbacks outweigh the benefits for me but let me know what you think! I'm happy to update the pros-cons list based on extra information.
I find this confusing, too. And as of now I wonder what's the real difference between List * and List _?
I've created a separate discussion for your question :)
one of the other motivations was that I always felt weird trying to explain the difference between foo : List a and foo : List a -> List a because it felt to me like a means something fundamentally different to me
in foo : List a, List a means “this is for sure an empty list” whereas in foo : List a -> List a, List a means “a list which might not be empty, but which must share an element type with this other list”
so I like that foo : List * makes that distinction visible
that said, I’m open to the possibility that the cure might be worse than the disease here :big_smile:
But I think we said we want to ban * from local variable definitions cause it is confusing and not useful. Like you can't append to a List * local variable cause it can never contain a type. So your local empty list probably should be a List _
a thing we could try is deprecating * and just see how the type annotations change, how we like it, etc.
Brendan Hansknecht said:
But I think we said we want to ban
*from local variable definitions cause it is confusing and not useful. Like you can't append to aList *local variable cause it can never contain a type. So your local empty list probably should be aList _
this is independent of * I think; the same is true of foo : List a
Sure, just trying to point out that foo: List a is kinda a strawman cause you don't see it in practice
Really we should only be thinking about use in functions. Cause that is the only useful place that * should ever go.
I think the confusion goes beyond that though
Sure, but we should just add a compiler error to all of those local cases and remove the class of user bugs.
So * would only ever be allowed in functions and a/b/etc would only be allowed in functions and type definitions.
As in even if there is confusion for those cases, we can add an error message to avoid users ever hitting it.
I think the errors for local variable defs are a good idea @Brendan Hansknecht, can you share why you think it would be worth it to keep * around for use in functions?
I'm actually pretty neutral. I think it is a bit clearer and quicker to parse than seeing List a, List b -> Bool
I just think restricting it some might make it reasonable overall and not too confusing
I wonder how much of this could be solved by giving a better mental model for generalized type variables (a, *) and inferred type variables
in
foo : List a,List ameans “this is for sure an empty list”
this is a true outcome but I think this might be a bad way to teach the concept. foo : List a means that foo is a list whose elements are every type. The outcome of that is the way to satisfy that is via an empty list. Vs foo : List _ means that foo is a list whose elements are one type, which will be inferred by the computer.
interesting! I hadn't thought of teaching it that way
Ayaz Hafiz said:
in
foo : List a,List ameans “this is for sure an empty list”this is a true outcome but I think this might be a bad way to teach the concept.
foo : List ameans thatfoois a list whose elements are every type. The outcome of that is the way to satisfy that is via an empty list. Vsfoo : List _means thatfoois a list whose elements are one type, which will be inferred by the computer.
I like this explanation! Should I change the explanation in the PR to reflect this?
Last updated: Jun 16 2026 at 16:19 UTC