Stream: ideas

Topic: newtypes


view this post on Zulip Richard Feldman (Jan 29 2022 at 17:27):

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)

view this post on Zulip Richard Feldman (Jan 29 2022 at 17:27):

also @Folkert de Vries mentioned that "opaque" is not a word people non-native English speakers are familiar with

view this post on Zulip Richard Feldman (Jan 29 2022 at 17:27):

@Chad Stearns I remember you had thoughts on this!

view this post on Zulip Anton (Jan 29 2022 at 19:00):

I'm a bit confused, how would you "expose everything about it"?

view this post on Zulip Richard Feldman (Jan 29 2022 at 19:55):

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:

view this post on Zulip Richard Feldman (Jan 29 2022 at 19:55):

although then again, I suppose a counterargument to that would be something like StrBuffer

view this post on Zulip Richard Feldman (Jan 29 2022 at 19:56):

where internally it holds a linked list of strings or something (not saying that's a good idea, but someone could do it)

view this post on Zulip Richard Feldman (Jan 29 2022 at 19:57):

so maybe it's actually fair to call that opaque

view this post on Zulip Ayaz Hafiz (Jan 29 2022 at 20:11):

I like newtype. "nominal" or "nameonly" may work too, but the first is likely not familiar either

view this post on Zulip jan kili (Jan 29 2022 at 20:17):

Regarding opacity, yup:

toStr : CustomerId -> Str
fromStr : Str -> CustomerId
toInt : CustomerId -> I32
fromInt : Int * -> CustomerId

How's it implemented? Nobody knows :shrug:

view this post on Zulip Richard Feldman (Jan 29 2022 at 21:01):

good point!

view this post on Zulip Zeljko Nesic (Jan 30 2022 at 03:02):

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

view this post on Zulip Anton (Jan 30 2022 at 08:27):

wrapped seems better to me as well. The name newtype sort of hides its primary purpose.

view this post on Zulip Richard Feldman (Jan 30 2022 at 15:42):

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

view this post on Zulip Richard Feldman (Jan 30 2022 at 15:43):

"unique type" is another option to consider, since it's...well, unique :big_smile:

view this post on Zulip Jeroen Engels (Jan 30 2022 at 20:49):

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

view this post on Zulip jan kili (Jan 30 2022 at 21:07):

bedroc

view this post on Zulip jan kili (Jan 30 2022 at 21:10):

Jokes aside, though, that's the one conceptualization I have for it - something like basetype might be universally clear

view this post on Zulip jan kili (Jan 30 2022 at 21:16):

Or maybe atom for succinctness?

view this post on Zulip Richard Feldman (Jan 30 2022 at 21:28):

when I searched for "unique type" https://en.m.wikipedia.org/wiki/Uniqueness_type came up :laughing:

view this post on Zulip Richard Feldman (Jan 30 2022 at 21:30):

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

view this post on Zulip Lucas Rosa (Jan 31 2022 at 02:57):

FWIW I prefer opaque because that word more aligns with their intended usage

view this post on Zulip Chad Stearns (Feb 06 2022 at 00:28):

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_.

view this post on Zulip Chad Stearns (Feb 06 2022 at 00:28):

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).

view this post on Zulip Chad Stearns (Feb 06 2022 at 00:32):

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.."

view this post on Zulip Chad Stearns (Feb 06 2022 at 00:38):

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.

view this post on Zulip Anton (Feb 06 2022 at 10:31):

I like "Contained type" as well.

view this post on Zulip Zeljko Nesic (Feb 06 2022 at 16:07):

a idea: Hiding type

view this post on Zulip jan kili (Feb 06 2022 at 16:48):

I like that! We could save three characters by going with shy foo = bar :laughing:


Last updated: Jun 16 2026 at 16:19 UTC