Stream: ideas

Topic: Get rid of `*`?


view this post on Zulip Anton (Jun 14 2024 at 14:06):

* 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:

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.

view this post on Zulip Akeshihiro (Jun 14 2024 at 15:31):

I find this confusing, too. And as of now I wonder what's the real difference between List * and List _?

view this post on Zulip Anton (Jun 14 2024 at 16:02):

I've created a separate discussion for your question :)

view this post on Zulip Richard Feldman (Jun 14 2024 at 16:54):

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

view this post on Zulip Richard Feldman (Jun 14 2024 at 16:58):

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”

view this post on Zulip Richard Feldman (Jun 14 2024 at 16:59):

so I like that foo : List * makes that distinction visible

view this post on Zulip Richard Feldman (Jun 14 2024 at 17:00):

that said, I’m open to the possibility that the cure might be worse than the disease here :big_smile:

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 17:01):

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 _

view this post on Zulip Richard Feldman (Jun 14 2024 at 17:01):

a thing we could try is deprecating * and just see how the type annotations change, how we like it, etc.

view this post on Zulip Richard Feldman (Jun 14 2024 at 17:03):

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 a List * local variable cause it can never contain a type. So your local empty list probably should be a List _

this is independent of * I think; the same is true of foo : List a

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 17:06):

Sure, just trying to point out that foo: List a is kinda a strawman cause you don't see it in practice

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 17:07):

Really we should only be thinking about use in functions. Cause that is the only useful place that * should ever go.

view this post on Zulip Richard Feldman (Jun 14 2024 at 17:08):

I think the confusion goes beyond that though

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 17:13):

Sure, but we should just add a compiler error to all of those local cases and remove the class of user bugs.

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 17:14):

So * would only ever be allowed in functions and a/b/etc would only be allowed in functions and type definitions.

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 17:15):

As in even if there is confusion for those cases, we can add an error message to avoid users ever hitting it.

view this post on Zulip Anton (Jun 14 2024 at 18:04):

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?

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 18:56):

I'm actually pretty neutral. I think it is a bit clearer and quicker to parse than seeing List a, List b -> Bool

view this post on Zulip Brendan Hansknecht (Jun 14 2024 at 19:06):

I just think restricting it some might make it reasonable overall and not too confusing

view this post on Zulip Ayaz Hafiz (Jun 16 2024 at 15:59):

I wonder how much of this could be solved by giving a better mental model for generalized type variables (a, *) and inferred type variables

view this post on Zulip Ayaz Hafiz (Jun 16 2024 at 16:01):

in foo : List aList a means “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.

view this post on Zulip Richard Feldman (Jun 16 2024 at 21:17):

interesting! I hadn't thought of teaching it that way

view this post on Zulip ElrohirGT (Jun 16 2024 at 21:29):

Ayaz Hafiz said:

in foo : List aList a means “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.

I like this explanation! Should I change the explanation in the PR to reflect this?


Last updated: Jun 16 2026 at 16:19 UTC