In the tutoral, we say that a NonEmptyList is a good example of an opaque type. I think it is only a kinda ok example and confuses people. I think we should find a different example.
The reason it is only kinda ok is due to what a good implementation would look like. A good implementation of NonEmptyList would be written in roc as:
NonEmptyList a : { head: a, rest: List a}
This type contains enough information by itself that it doesn't strictly need to be opaque. You could also write NonEmptyList as:
NonEmptyList a := List a
But then a function like first is written as:
first = \@NonEmptyList list ->
when List.first list is
Ok x -> x
Err _ -> crash "this shouldn't be possible"
Just doesn't feel like a good example.
I think. we should change this to something simpler that needs verification. My top thoughts are Email, Url, and Path. All of which could be seen as just a wrapper around a Str or List U8, but you would add verification when creating one. That way any @Email is guaranteed to be in the right format.
It also means we could write up a super simple in tutorial example to help people grok it better.
Thoughts? Better type suggestions?
I agree! email sounds good
Maybe we could show an identical example to username, but with fromStr returning a Result Email [InvalidEmail].
Except emails is actually suoer complicated to validate (if you wanna follow the spec) :sweat_smile:
Yeah, might want to just call to a fake validation function or do some basic form of validation with a comment that it is just for show
The complete implementation has been left as an exercise for the reader :big_smile:
String.contains s "@" oughta do.
Roughly this sounds easy enough: https://www.mailboxvalidator.com/resources/articles/acceptable-email-address-syntax-rfc/
Maybe just split at @ and then check the contained characters as a simple proxy
Just for example purposes
Last updated: Jun 16 2026 at 16:19 UTC