Stream: ideas

Topic: :: for type annotation


view this post on Zulip Josh (Nov 26 2023 at 15:55):

Shouldn’t the syntax for type annotation be :: instead of : ?

Advantages of ::

  1. Same as haskell
  2. Not confusingly same as record key:value separator

Advantages of :

  1. Fewer keypresses/characters to get the job done :big_smile:

view this post on Zulip Asier Elorz (he/him) (Nov 26 2023 at 15:59):

In Elm, a single colon : is used to separate declaration name from type annotation. Since Roc takes a lot of inspiration from Elm, and wants to be similar and easy to learn for people who already know Elm, chances are that this is the origin and reason behind the single colon in Roc, even if it is different from Haskell. I don't know why Elm decided to deviate from Haskell there though. Someone who knows Czaplicki may be able to answer that.

view this post on Zulip Andrew C (Nov 26 2023 at 16:02):

Advantages of :

2. Same as elm (the parent language of roc), typescript, go and scala

view this post on Zulip Andrew C (Nov 26 2023 at 16:03):

  1. I like that the type annotation is the same as the record field, it means that I can paste the type of a record and edit it to the values quickly, something that I find myself doing a lot in elm.

view this post on Zulip Josh (Nov 26 2023 at 16:21):

Andrew C said:

  1. I like that the type annotation is the same as the record field, it means that I can paste the type of a record and edit it to the values quickly, something that I find myself doing a lot in elm.

Oh I just meant the outer one, so e.g. using :: would be

amy :: { firstName : Str, lastName : Str }
amy = { firstName: "Amy", lastName: "Lee" }

view this post on Zulip Sky Rose (Nov 26 2023 at 16:27):

Josh said:

Advantages of :

  1. Fewer keypresses/characters to get the job done :big_smile:

This is something that you'll type _a lot_, so this adds up. Normally syntax / keystrokes issues aren't worth worrying about too much, but if you multiply that little bit of effort times every single function ever defined in Roc, it begins to matter.

I vaguely remember seeing something a long time ago about this being the reason for Elm using : for types and :: for the rarely-used cons operator, which is opposite of Haskell.

view this post on Zulip Andrew C (Nov 26 2023 at 17:08):

Josh said:

Oh I just meant the outer one, so e.g. using :: would be

amy :: { firstName : Str, lastName : Str }
amy = { firstName: "Amy", lastName: "Lee" }

Wouldn't that be really confusing? How do you remember whether you're supposed to use :: or : for a type? What about records inside records? I'm not keen on that mix, personally.

view this post on Zulip Richard Feldman (Nov 26 2023 at 17:24):

so as I understand it, Robin Milner used : in the original ML, which is what Standard ML and OCaml used too (and later Elm, Idris, and now Roc).

Miranda used :: instead. As I understand it, the motivation was to free up : for the cons operator, with the idea being that Miranda was very focused on laziness and had inferred types anyway, so the expectation was that people would be writing cons far more often than writing type annotations.

Haskell, being a direct descendant of Miranda, kept this - presumably because it's what everyone on the Haskell Committee was already familiar with. PureScript later kept it because (I assume, although I've never asked him directly) Phil was used to it from Haskell.

view this post on Zulip Richard Feldman (Nov 26 2023 at 17:26):

in that historical context, it seems like :: for types ended up being based on an expectation that turned out not to be true for the languages after Miranda (all of which write type annotations far more often than cons!) so I think it makes sense to stick with the original : for types :big_smile:

view this post on Zulip Andrew C (Nov 26 2023 at 18:06):

Delightful to have a little functional programming history, thank you! Miranda heavily inspired Orwell, the first functional programming language I learned before I switched to Gofer for the Eq and Ord type classes that made our printed fat easier to write, and later HUGS and eventually Haskell itself after it adopted type classes. I was surprised when elm (which does not have type classes) became my favourite programming language.

view this post on Zulip Andrew C (Nov 26 2023 at 18:19):

Roc has the potential to take over. As soon as there's a widows GUI program platform, it'll probably win. What you said, @Richard Feldman, in a recent podcast about Electron and Tauri being in a way objectionable because you're turning your gui into a document only to turn it back into a gui resonated with me.

I can't wait until I can write a gui using functional programming (with the elm architecture) but then _not_ have to write the IO end in another language for speed.

At the moment it's tempting to think that Tauri wouldn't need a very thick wrapper to become a roc platform, but having it sit on top of gtk or wx or some other desktop ui framework or something new and more functional is the dream.

view this post on Zulip Richard Feldman (Nov 26 2023 at 18:19):

I'm very excited for a viable Electron alternative in Roc! :smiley:

view this post on Zulip Richard Feldman (Nov 26 2023 at 18:20):

definitely a big project, but I think the payoff would be very much worth the effort

view this post on Zulip Josh (Nov 26 2023 at 18:37):

Current:

amy = { firstName : "Amy", lastName : "Lee" }
amy : { firstName : Str, lastName : Str }

Elm:

amy = { firstName = "Amy", lastName = "Lee" }
amy : { firstName : Str, lastName : Str }

Proposed:

amy = { firstName : "Amy", lastName : "Lee" }
amy :: { firstName : Str, lastName : Str }

IMHO the Elm approach is also nice, but the proposed change makes more sense for how Roc does other things like default record fields and opaque types...

\{ table = height, width, title? "oak", -> [...] #function accepting record with defaulted fields
table :: { height : Pixels, width : Pixels, title ? Str, -> [...] #and its type, proposed
Username := { firstName : Str, lastName : Str } #opaque type

So the operators for working with defs are = := :: and the operators for working with records are { } ? :

You'd never have to explain : being an oddball, both connecting a record key and value, and also annotating a def with a non-opaque type.

view this post on Zulip Brendan Hansknecht (Nov 26 2023 at 21:10):

Interesting. Always surprising to see what people find odd or to have more friction. To me, :: just makes me think of templates and submodule selection. Nothing for type definitions. Just coming from different contexts.

view this post on Zulip Brendan Hansknecht (Nov 26 2023 at 21:16):

What are the theoretically gains of the new syntax? Just not needing to explain : is used both in record definitions and record creation....oh, and type definition.

So instead of having 3 uses, we make the symbols distinct, but use more symbols?

view this post on Zulip Brendan Hansknecht (Nov 26 2023 at 21:17):

Side thought, one potential gain of using = for record assignment is that it will make the record backpassing related syntax look more natural.... probably.

view this post on Zulip Jacob (Nov 26 2023 at 21:18):

The only thing I don't like (although such a minor thing) is that : is used for type annotations inside a record and setting the value of a field in a record. = is much more intuitive, it just feels like the right symbol for the operation being done.

view this post on Zulip Norbert Hajagos (Nov 26 2023 at 23:11):

My background is mainly JS. I figure it would be the same for a lot of people. Having record field assignment be : makes it nice and comfy for a lot of people. Plus, I can always dbg print my records and copy-paste the result to a website / app that expects json, but allows the relaxed, javascript source code styled form as well with no " -s around the keys. I know it will be platform depended, but I think most of them will stick to the style that the source code is written in.

I haven't done any functional programming before, but : both for the type defs and the field assignement did't confuse me at all. Alas, typescript did that to me. Lots of :-s there.

view this post on Zulip Josh (Nov 27 2023 at 17:43):

when i encounter an exciting new minimalist language, i've got to bike shed any syntax nits right away. If and when it takes over the world, it'll clearly be too late to change such things, and then i'll be stuck with my regrets for not having said anything earlier. :laughing:

view this post on Zulip Kevin Gillette (Nov 30 2023 at 03:59):

In my mind, : for both types and record fields is consistent, though I think I read : as "is a"


Last updated: Jun 16 2026 at 16:19 UTC