3 ms·
Branding doesn't need to be weird and arbitrary, see Pythons NewType: https://docs.python.org/3/library/typing.html#typing.NewType https://docs.python.org/3/lib
by whilenot-dev 1y ago
Branding doesn't need to be weird and arbitrary, see Pythons NewType: https://docs.python.org/3/library/typing.html#typing.NewType https://docs.python.org/3/library/typing.html#typing.NewType
Reading TFA now, Pythons NewType seems to be equal to Haskells newtype. Yes, it's a hack for the type checker to work around existing language semantics and feels unergonomic at times when Parse, Don't Validate needs to fall back to plain validation, but I wouldn't call it neither weird nor arbitrary.
- o11c 1y agoPython defaults uses nominal typing so isn't prone to this problem anyway. The kind of "branding" I'm talking about is a hack only needed for structural typing systems. Consider something inspired by the C locale API, for example: class RealLocale: name: str const C_LOCALE = RealLocale("C"); # Each of these can be passed to *some*, but not all, locale functions, # which will check for them by identity before doing the logic for `RealLocale`. singleton NO_LOCALE # used for both "error" and "query" singleton THREAD_LOCALE singleton GLOBAL_LOCALE singleton ENV_LOCALE In a structural typing system, it is impossible to write a function that takes a union including more than one of `{NO_LOCALE, THREAD_LOCALE, GLOBAL_LOCALE, ENV_LOCALE}`, since they have no contents and thus cannot be distinguished. You have to hack around it, by some kind of casting and/or adding a member that's not actually present/useful at runtime. And this kind of need is quite common. So I maintain that structural typing is not a serious type system proposal. (Then again, the man proponent for structural typing is TypeScript, which even in $CURRENTYEAR still lacks even a way to specify ubiquitous needs like "integer" or "valid array index").
- voidmain 1y agoI think a type system that permits a type (no_locale=()) | (thread_locale=()) | (global_locale=()) | (env_locale=()) would generally be considered structural. I think newtypes and structure field names are isomorphic in functionality. Where a nominal type system would use newtype(tag,X) a structural one could use struct{tag:X} (and this holds even if X is the unit/singleton type).