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.
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.
Ah, so the langref says it should work -- but it's not wired up yet in the type checker by the look of things
I was looking at this https://github.com/roc-lang/roc/blob/main/docs/langref/types.md#nominal-types which starts with UserID := U64.
We should make a GH Issue to track this as not yet implemented
Sounds good, I'll file an issue
1 sec, I might have Claude do it
Done https://github.com/roc-lang/roc/issues/9770
Ah, I’ve been wondering about this too!
I can take a look at this!
Last updated: Jul 23 2026 at 13:15 UTC