Stream: ideas

Topic: reddit type variable syntax


view this post on Zulip Anton (Apr 17 2023 at 12:27):

A nice suggestion from reddit user WhyteVuhuni:
"""
The * was confusing until I read what it meant. I think that could've been avoided.

doTheThing : {} -> { x: Str, y: Str }*

Also, my brain's lexer gave me warnings on {}a, the first time I saw it I thought it was a typo in the tutorial. I think something like this might've been more intuitive and pretty:

doTheThing : {} -> { x: Str, y: Str, ... }
doTheThing : { x: Str, ..a } -> { x: Str, ..a }
fail : {} -> [ Err Error1, Err Error2, ... ]

... is consistent with Nix's syntax, while ..a is somewhat consistent with Rust's syntax, aka "it pulls some more fields from generic type variable a".
"""

view this post on Zulip Richard Feldman (Apr 17 2023 at 12:55):

these are interesting, although this would have to be allowed, and would look weird to me:

doTheThing : { x: Str, ..* } -> Str

view this post on Zulip Richard Feldman (Apr 17 2023 at 12:56):

as an aside, it's interesting how much more often open record syntax comes up as a raised eyebrow from beginners now that tag union literals don't syntactically show a type variable anymore :big_smile:

view this post on Zulip Anton (Apr 17 2023 at 13:08):

Could we not use three dots for that scenario?

doTheThing : { x: Str, ... } -> Str

Instead of

doTheThing : { x: Str, ..* } -> Str

view this post on Zulip Richard Feldman (Apr 17 2023 at 13:20):

it would still have to be supported

view this post on Zulip Richard Feldman (Apr 17 2023 at 13:20):

like * is just a valid type variable syntax; it's syntactically always allowed anywhere a named type variable is allowed

view this post on Zulip Andrei Vasiliu (Apr 17 2023 at 14:17):

Maybe allow ..* anyway, but have a lint/warning that asks the user to replace it with ....

view this post on Zulip Richard Feldman (Apr 17 2023 at 14:36):

that's a possibility, but needing to add all that is definitely a weakness of the syntax as an idea

view this post on Zulip Luke Boswell (Apr 17 2023 at 19:44):

Richard Feldman said:

these are interesting, although this would have to be allowed, and would look weird to me:

doTheThing : { x: Str, ..* } -> Str

Would it be possible to remove the * altogether from the language and just use lowercase letters? I've thought that previously, and wondered why we need the * character? I assume it has a special place in type system notation and looks familiar. But then in every place where it is used, we could also use a letter and it still looks ok and means the same thing right? If we removed it would this then make this syntax acceptable? I think it looks ok, and is easier to understand at first glance. Would this significantly complicate things?

view this post on Zulip Georges Boris (Apr 17 2023 at 21:38):

doTheThing : { x: Str, _ } -> Str

following @Luke Boswell 's suggestion - maybe type variables should follow the same rules as all variables as in only alphanumeric characters and _ for wildcard matching? then in type definitions the _ could be used for these situations. just throwing ideas :grinning_face_with_smiling_eyes:

view this post on Zulip Notification Bot (Apr 17 2023 at 23:03):

18 messages were moved from this topic to #ideas>should we have the * type variable? by Richard Feldman.

view this post on Zulip Anton (Apr 18 2023 at 08:54):

Using the wildcard may be confusing because we currently use it to match with a single thing, not with nothing or multiple things.

view this post on Zulip Anton (Apr 18 2023 at 08:58):

But then in every place where it is used, we could also use a letter and it still looks ok and means the same thing right?

I think it is nice to use a symbol here because it shows this really is a different case. I don't love the * but I do think a symbol is better.

view this post on Zulip Andrei Vasiliu (Apr 18 2023 at 13:32):

As a possible alternative to this:

doTheThing : { x: Str, ..a } -> { x: Str, ..a }

Can the latter repetition of { x: Str, ..a } ever change (e.g. be further constrained)? I'd imagine not, since the type variable a refers to the record as a whole, rather than just the extra fields. In which case, perhaps the previously suggested as, but outside the record, would be better:

doTheThing : { x: Str, ... } as a -> a

Might help make some function signatures shorter too. Not sure that it looks as nice though.

view this post on Zulip Anton (Apr 18 2023 at 13:47):

doTheThing : { x: Str, ... } as a -> a

I'm struggling to make up my mind over this one :p

view this post on Zulip Andrei Vasiliu (Apr 18 2023 at 14:19):

Does anyone know of any examples of real code that uses record or tag union constraints? I'm curious how big type signatures are in practice, and if the constraint is over a small part of the input, or over the whole input.

view this post on Zulip Andrei Vasiliu (Apr 18 2023 at 14:51):

Given:

Dict.insert : Dict k v, k, v -> Dict k v
    where k implements Hash & Eq

This, or whatever would be similar to the syntax of abilities, would probably be prettier:

doTheThing : a -> a
    where a is { x: Str, ... }

...but unnecessarily long. Unless this is only used very rarely, in which case the added intuitive readability is worth it.


Last updated: Jun 16 2026 at 16:19 UTC