<p>Imagine a structural type system with the ability to create nominally-typed aliases:</p>
<pre><code>type Foo = {foo: string, bar: number}

nominal type NominalFoo = Foo
</code></pre>
<p>Then the rules for assignability are simple: <code>NominalFoo</code> is always assignable to <code>Foo</code>, <code>Foo</code> can be downcast safely to <code>NominalFoo</code>, and <code>Foo</code> or other nominal aliases are not otherwise assignable to <code>NominalFoo</code>.</p>
<p>Is there anything about this which would cause problems? Particularly, does it make the implementation difficult, does it cause unsoundness, or are more assignability rules needed for this to be useful?</p>

<structural-types><nominal-types>
Is it this easy to add nominal types to a structural type system?
CC BY-SA 4.0
2024-06-11T00:24:20.670Z
**Comments have been [moved to chat](https://chat.stackexchange.com/rooms/153599/discussion-on-question-by-kaya3-is-it-this-easy-to-add-nominal-types-to-a-struct); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.
lyxal
<p>A nominal type is isomorphic to a structural record type with a language-guaranteed unique member.<br />
For instance, I wrote a compiler where unions discriminate nominal types by treating them as containing a pointer to a string representing <em>their name</em> in ROM.<br />
<a href="https://en.wikipedia.org/wiki/Virtual_method_table" rel="noreferrer">Virtual tables and pointers</a> are another example of such a discriminant.<br />
So yes, it is <em>that</em> easy.</p>
<p>Many languages have typesystems with both nominal and structural types.<br />
For example,</p>
<ul>
<li>TypeScript's <code>type</code>s and <code>interface</code>s are structural, but its <code>enum</code>s are nominal,</li>
<li>Carbon's <code>struct</code>s are structural, but its <code>class</code>es are nominal,</li>
<li>Go's <code>struct</code>s are nominal, but its <code>interface</code>s are structural,</li>
<li>Haskell's <code>type</code>s are structural, but its <code>newtype</code>s are nominal.</li>
</ul>
<blockquote>
<p>Foo can be downcast safely to NominalFoo, and Foo or other nominal aliases are not otherwise assignable to NominalFoo.</p>
</blockquote>
<p>Typically, such downcasts are possible but explicit.<br />
This is especially desirable in languages marketing themselves as &quot;low-level&quot; if structural types expose a <a href="https://en.wikipedia.org/wiki/Row_polymorphism" rel="noreferrer">Row-Polymorphic</a> behaviour where <code>{ x: a, y: b } &lt;: { y: b, x: a, z: c }</code>, as such a downcast requires use of a conversion routine and cannot rely on simple <code>memcpy</code>, though that has more to do with the structural part than the nominal.<br />
An example of where this is not relevant but still requires explicit casts is <a href="http://skew-lang.org/#docs" rel="noreferrer">Skew</a> (under §Wrapped Types).</p>

CC BY-SA 4.0
2023-06-04T01:34:27.500Z
2023-06-04T01:55:20.587Z
2023-06-04T01:55:20.587Z
Longinus
# Is it this easy to add nominal types to a structural type system?
Posted by: username_0 on 2023-06-02
Imagine a structural type system with the ability to create nominally-typed aliases:
type Foo = {foo: string, bar: number}

nominal type NominalFoo = Foo

Then the rules for assignability are simple: NominalFoo is always assignable to Foo, Foo can be downcast safely to NominalFoo, and Foo or other nominal aliases are not otherwise assignable to NominalFoo.
Is there anything about this which would cause problems? Particularly, does it make the implementation difficult, does it cause unsoundness, or are more assignability rules needed for this to be useful?
**Tags:** structural-types nominal-types
> **Comments:**
> **username_1**: **Comments have been [moved to chat](https://chat.stackexchange.com/rooms/153599/discussion-on-question-by-kaya3-is-it-this-easy-to-add-nominal-types-to-a-struct); please do not continue the discussion here.** Before posting a comment below this one, please review the [purposes of comments](/help/privileges/comment). Comments that do not request clarification or suggest improvements usually belong as an [answer](/help/how-to-answer), on [meta], or in [chat]. Comments continuing discussion may be removed.  
---
## 1 answers
### Answer by username_2 on 2023-06-04. Score: 9 | Accepted answer
A nominal type is isomorphic to a structural record type with a language-guaranteed unique member.  
For instance, I wrote a compiler where unions discriminate nominal types by treating them as containing a pointer to a string representing *their name* in ROM.  
[Virtual tables and pointers](https://en.wikipedia.org/wiki/Virtual_method_table) are another example of such a discriminant.  
So yes, it is *that* easy.

Many languages have typesystems with both nominal and structural types.  
For example,

* TypeScript's `type`s and `interface`s are structural, but its `enum`s are nominal,
* Carbon's `struct`s are structural, but its `class`es are nominal,
* Go's `struct`s are nominal, but its `interface`s are structural,
* Haskell's `type`s are structural, but its `newtype`s are nominal.

> Foo can be downcast safely to NominalFoo, and Foo or other nominal aliases are not otherwise assignable to NominalFoo.

Typically, such downcasts are possible but explicit.  
This is especially desirable in languages marketing themselves as "low-level" if structural types expose a [Row-Polymorphic](https://en.wikipedia.org/wiki/Row_polymorphism) behaviour where `{ x: a, y: b } <: { y: b, x: a, z: c }`, as such a downcast requires use of a conversion routine and cannot rely on simple `memcpy`, though that has more to do with the structural part than the nominal.  
An example of where this is not relevant but still requires explicit casts is [Skew](http://skew-lang.org/#docs) (under §Wrapped Types).
---
