|
1 | 1 |
|
2 | 2 | # Subtyping and Algebraic Subtyping |
3 | 3 |
|
| 4 | +<script type="module" src="/javascripts/editor.js"></script> |
| 5 | +<link rel="stylesheet" href="/static/styles.css"> |
| 6 | + |
4 | 7 | Subtyping is mathematically represented as a subset relation, \( A \subseteq B \), such that \( \forall t \in A, t \in B \). This interpretation allows subtyping to reflect a preorder relation, which becomes a partial order under equivalence (\( A \leq B \land B \leq A \implies A = B \)). The introduction of least upper bounds (lub, \( A \sqcup B \)) and greatest lower bounds (glb, \( A \sqcap B \)) converts this structure into a lattice. When combined with the universal top type (\( \top \)) and bottom type (\( \bot \)), the lattice becomes bounded, satisfying: |
5 | 8 |
|
6 | 9 | $$ |
|
93 | 96 |
|
94 | 97 | This states that the intersection of function types corresponds to the union of parameter types and the intersection of return types. |
95 | 98 |
|
| 99 | +For example: |
| 100 | + |
| 101 | +<div class="code-editor" id="code-union-dist"> |
| 102 | + |
| 103 | +``` |
| 104 | +(Int -> String) & (Float -> Bool) |
| 105 | +``` |
| 106 | +</div> |
| 107 | +<div class="button-container"> |
| 108 | + <button class="md-button button-run" onclick="runCodeInEditor('code-union-dist', 'output-union-dist', true)">Run Example</button> |
| 109 | +</div> |
| 110 | +<div id="output-union-dist" class="result-editor"></div> |
| 111 | + |
| 112 | +Similarly, the union of function types results from the intersection of parameter types and the union of return types. |
| 113 | + |
96 | 114 | $$ |
97 | 115 | (A_1 \to B_1) \sqcup (A_2 \to B_2) = (A_1 \sqcap A_2) \to (B_1 \sqcup B_2) |
98 | 116 | $$ |
99 | 117 |
|
100 | | -Similarly, the union of function types results from the intersection of parameter types and the union of return types. |
| 118 | +For example: |
| 119 | +<div class="code-editor" id="code-intersection-dist"> |
| 120 | + |
| 121 | +``` |
| 122 | +(Int -> String) | (Float -> Bool) |
| 123 | +``` |
| 124 | +</div> |
| 125 | +<div class="button-container"> |
| 126 | + <button class="md-button button-run" onclick="runCodeInEditor('code-intersection-dist', 'output-intersection-dist', true)">Run Example</button> |
| 127 | +</div> |
| 128 | +<div id="output-intersection-dist" class="result-editor"></div> |
| 129 | + |
101 | 130 |
|
102 | 131 | ## Records |
103 | | -Subtyping for record types aligns with structural subtyping, allowing more permissive views: |
| 132 | +Subtyping for record types aligns with structural subtyping, where records are compatible if they share the same fields and types. The typing rule for record types is: |
104 | 133 |
|
105 | 134 | $$ |
106 | 135 | \begin{align} |
|
153 | 182 |
|
154 | 183 |
|
155 | 184 |
|
| 185 | +### Union and Intersection Rules for Record Types |
| 186 | + |
| 187 | +In algebraic subtyping, **union** (\( \sqcup \)) and **intersection** (\( \sqcap \)) types can also be extended to **record types**. These operations allow record subtyping to support partial and combined views of records, ensuring compatibility and flexibility in handling structured data. |
| 188 | + |
| 189 | +#### Union of Record Types |
| 190 | +The union of two record types combines their fields, allowing overlapping fields to resolve to the union of their respective types: |
| 191 | + |
| 192 | +$$ |
| 193 | +\{\overline{l_i : A_i}^{i \in S}\} \sqcup \{\overline{l_i : B_i}^{i \in T}\} = \{\overline{l_i : A_i \sqcup B_i}^{i \in S \cap T}, \overline{l_j : A_j}^{j \in S \setminus T}, \overline{l_k : B_k}^{k \in T \setminus S}\} |
| 194 | +$$ |
| 195 | + |
| 196 | +- For shared fields \( l_i \in S \cap T \), the resulting type is the union of their individual types \( A_i \sqcup B_i \). |
| 197 | +- For fields exclusive to one record (e.g., \( l_j \in S \setminus T \) or \( l_k \in T \setminus S \)), their types remain unchanged. |
| 198 | + |
| 199 | +For example: |
| 200 | + |
| 201 | +<div class="code-editor" id="code-union-record"> |
| 202 | + |
| 203 | +``` |
| 204 | +(record { a: Int; b: String }) | (record { b: Float; c: Bool }) |
| 205 | +``` |
| 206 | +</div> |
| 207 | + |
| 208 | +<div class="button-container"> |
| 209 | + <button class="md-button button-run" onclick="runCodeInEditor('code-union-record', 'output-union-record', true)">Run Example</button> |
| 210 | +</div> |
| 211 | +<div id="output-union-record" class="result-editor"></div> |
| 212 | + |
| 213 | + |
| 214 | +#### Intersection of Record Types |
| 215 | +The intersection of two record types combines their fields similarly, but overlapping fields resolve to the intersection of their types: |
| 216 | + |
| 217 | +$$ |
| 218 | +\{\overline{l_i : A_i}^{i \in S}\} \sqcap \{\overline{l_i : B_i}^{i \in T}\} = \{\overline{l_i : A_i \sqcap B_i}^{i \in S \cap T}\} |
| 219 | +$$ |
| 220 | + |
| 221 | +- Only fields common to both records (\( l_i \in S \cap T \)) are preserved in the resulting record. |
| 222 | +- For shared fields, the resulting type is the intersection of their individual types \( A_i \sqcap B_i \). |
| 223 | +- Fields exclusive to one record are excluded from the intersection. |
| 224 | + |
| 225 | +For example: |
| 226 | + |
| 227 | +<div class="code-editor" id="code-intersect-record"> |
156 | 228 |
|
| 229 | +``` |
| 230 | +(record { a: Int; b: String }) & (record { b: String; c: Bool }) |
| 231 | +``` |
| 232 | +</div> |
157 | 233 |
|
| 234 | +<div class="button-container"> |
| 235 | + <button class="md-button button-run" onclick="runCodeInEditor('code-intersect-record', 'output-intersect-record', true)">Run Example</button> |
| 236 | +</div> |
| 237 | +<div id="output-intersect-record" class="result-editor"></div> |
158 | 238 |
|
159 | 239 |
|
160 | 240 |
|
|
0 commit comments