Stream: beginners

Topic: Accessing the value of unstructured nominal and opaque types


view this post on Zulip Aurélien Geron (Jun 23 2026 at 06:12):

I'm a bit confused by nominal types and opaque types when they are not based on a union or a record. For example:

Distance := U64.{
    new : U64 -> Distance
    new = |d| d
}

main! = |_| {
    d = Distance.new(123)
    dbg d
    Ok({})
}

This code fails on new = |d| d because it says that d is a U64 but it expected a Distance. Shouldn't it be able to automatically convert from U64 to Distance in this case? If not, then how can new be implemented? Is there a special syntax? Or are we simply not supposed to define nominal types for such "raw" types? In the meantime, I'm using {distance: U64} as a workaround.

view this post on Zulip Luke Boswell (Jun 23 2026 at 06:53):

I didn't know you could make a nominal type like that... I have a vague memory that it was limited to records and tag unions.

view this post on Zulip Luke Boswell (Jun 23 2026 at 07:03):

Ah, so the langref says it should work -- but it's not wired up yet in the type checker by the look of things

view this post on Zulip Aurélien Geron (Jun 23 2026 at 07:03):

I was looking at this https://github.com/roc-lang/roc/blob/main/docs/langref/types.md#nominal-types which starts with UserID := U64.

view this post on Zulip Luke Boswell (Jun 23 2026 at 07:03):

We should make a GH Issue to track this as not yet implemented

view this post on Zulip Aurélien Geron (Jun 23 2026 at 07:04):

Sounds good, I'll file an issue

view this post on Zulip Luke Boswell (Jun 23 2026 at 07:04):

1 sec, I might have Claude do it

view this post on Zulip Luke Boswell (Jun 23 2026 at 07:08):

Done https://github.com/roc-lang/roc/issues/9770

view this post on Zulip Bryce Miller (Jun 23 2026 at 11:00):

Ah, I’ve been wondering about this too!

view this post on Zulip Jared Ramirez (Jun 23 2026 at 21:13):

I can take a look at this!


Last updated: Jul 23 2026 at 13:15 UTC