Interestingly, python has included structural subtyping in 3.8[1] as part of the typing module.
Interestingly, python has included structural subtyping in 3.8[1] as part of the typing module.
Structural vs. nominal typing is pretty well known in programming language design circles, but circulating that knowledge is a constant uphill challenge. One of the reasons many of us are frustrated with Go's designers were how quickly they threw this work under the bus as part of their initial marketing strategy, which kind of knocks away the ladder for anyone else who is curious to learn about this stuff.
AFAIK SML is nominal. OCaml has a structural subsystem in that its object system is structural. The vast majority of the language is nominally typed.
> It's probably more that most mainstream typed languages, like C, C++, Java, C#, etc. have mainly gone down the nominal route
It's not just mainstream typed languages. Almost all statically typed languages use nominative typing. Tt doesn't have any real drawback and it's just simpler to understand and work with.
A language like typescript would go with a structural system because it's a much easier bridge and sell from an object-oriented dynamically typed world.
I guess I was referring to how records are structural. Although granted tagged unions are nominal, and you can get nominal typing through modules. I was probably wrong in posing it as 'one or the other' - seeing as many languages have a mix of both. I'm definitely not saying that nominal typing is bad, it's just that it's nice to have the option to go structural if you want, and many have not known that this option exists.
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.