|
|
|
|
|
by momentoftop
2341 days ago
|
|
Modules are structurally subtyped in SML. They are not nominally subtyped. You do give them names for readability and reuse, but the name is not important to the typechecking. Module types (signatures) are checked according to the types of the fields they have, with one module type being a subtype of another if it includes the other's fields. For instance, if I have a functor: functor F(S : sig val x : int end) = struct ... end
then I can apply F to any module that includes a field x of type int. I don't even have to name the functor argument: structure Foo = F(struct val x = 3 val y = 4 end)
Unions, on the other hand, have nothing to do with subtyping. In the union datatype foo = Bar | Baz
val foo1 = Bar
val foo2 = Baz
There is no subtyping. There is exactly one type in question, which is "foo", and no other types to form a subtyping relationship.You might be thinking instead about how some languages implement algebraic data types over a language like Java by replacing "foo" with a supertype and implementing the variants as subtypes. Scala and Kotlin are examples of this. Doing things this way allows you to do interesting things that are not possible in SML, such as typing for exactly the variant you expect. Ocaml has always had, in addition to normal records, structurally typed records and polymorphic variants. It also has SML's structurally typed module system, though goes much further by allowing modules as runtime values. |
|