so for https://github.com/rtfeldman/roc/issues/2214 I was thinking about using the word "newtype" instead of "opaque type" - that's the term both Rust and Haskell use for this - see https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html and https://wiki.haskell.org/Newtype - and it seems intuitive, since literally what you're doing is making a new type (even if you decide to expose everything about it, thus making it not really opaque per se)
also @Folkert de Vries mentioned that "opaque" is not a word people non-native English speakers are familiar with
@Chad Stearns I remember you had thoughts on this!
I'm a bit confused, how would you "expose everything about it"?
like if I make toStr : WrappedStr -> Str and fromStr : Str -> WrappedStr, and neither of those loses any information, then I'm not really hiding anything :big_smile:
although then again, I suppose a counterargument to that would be something like StrBuffer
where internally it holds a linked list of strings or something (not saying that's a good idea, but someone could do it)
so maybe it's actually fair to call that opaque
I like newtype. "nominal" or "nameonly" may work too, but the first is likely not familiar either
Regarding opacity, yup:
toStr : CustomerId -> Str
fromStr : Str -> CustomerId
toInt : CustomerId -> I32
fromInt : Int * -> CustomerId
How's it implemented? Nobody knows :shrug:
good point!
Me gusta new type but my favorite term for this is wrapped.
CustomerId is just a wrapped Int64.
Being wrapped means it has it's own shape.
And I think Dutch also wrap things, right? @Folkert de Vries :D
wrapped seems better to me as well. The name newtype sort of hides its primary purpose.
a thing that's kinda weird to me about "wrapped" as the name for this is that there are other ways to wrap types in other types, e.g. I can wrap a Foo type in a record with { value : Foo } or in a single-tag union, like [ Value Foo ], but that's not the same as defining a whole new type that's incompatible with others
"unique type" is another option to consider, since it's...well, unique :big_smile:
I was reading the thread and was thinking of unique as well. Or maybe "separate". I like unique more, but it should be fairly clear that it's not about the uniqueness of the value or something
bedroc
Jokes aside, though, that's the one conceptualization I have for it - something like basetype might be universally clear
Or maybe atom for succinctness?
when I searched for "unique type" https://en.m.wikipedia.org/wiki/Uniqueness_type came up :laughing:
I think there's definitely value in using a standard name for something as long as it's a reasonable and easy to learn name
FWIW I prefer opaque because that word more aligns with their intended usage
Yeah I had a negative view about "newtype". Like, I hear ya when you say " it seems intuitive, since literally what you're doing is making a new type" @Richard Feldman , but then my criticism is that description also fits with non-newtypes as well. Like when one programs they are "literally making new types" just normally.
But I guess its intuitive because a newtype is _only_ new. Thats the _only_ thing thats different about it compared to what its a newtype _of_.
Thats my view. My thoughts would also apply to "unique" type, since most types are unique as well. (Color = Red | Blue is unique compared to Direction = Up | Down).
Maybe "wrapped" too, since most types "wrap" something else.. altho I kind of like "wrapped" because thats usually how I describe types like these "..DrawingId just wraps a normal Id.."
More ideas?
"Contained type"
"Controlled type"
"Managed type"
Idk. I am trying to most directly reference the purpose of these types as I see it, which is to take an ordinary value and force it to be treated differently so that its usage can be controlled by an api.
I like "Contained type" as well.
a idea: Hiding type
I like that! We could save three characters by going with shy foo = bar :laughing:
Last updated: Jun 16 2026 at 16:19 UTC