Comment by gpm

3 days ago

I wonder if it's useful to think of this as go is low type-system-complexity and rust is high type-system-complexity. Where type system complexity entails a tradeoff between the complexity of the language and how powerful the language is in allowing you to define abstractions.

As an independent axis from close to the underlying machine/far away from the underlying machine (whether virtual like wasm or real like a systemv x86_64 abi), which describes how closely the language lets you interact with the environment it runs in/how much it abstracts that environment away in order to provide abstractions.

Rust lives in high type system complexity and close to the underlying machine environment. Go is low type system complexity and (relative to rust) far from the underlying machine.

I think this is insightful! I'm going to ponder it, thank you. I think it may gesture towards what I'm trying to get at.

> Where type system complexity entails a tradeoff between the complexity of the language and how powerful the language is in allowing you to define abstractions.

I don't think that's right. The level of abstraction is the number of implementations that are accepted for a particular interface (which includes not only the contract of the interface expressed in the type system, but also informally in the documentation). E.g. "round" is a higher abstraction than "red and round" because the set of round things is larger than the set of red and round things. It is often untyped languages that offer the highest level of abstraction, while a sophisticated type system narrows abstraction (it reduces the number of accepted implementations of an interface). That's not to say that higher abstraction is always better - although it does have practical consequences, explained in the next paragraph - but the word "abstraction" does mean something specific, certainly more specific than "describing things".

How the level of abstraction is felt is by considering how many changes to client code (the user of an interface) is required when making a change to the implementation. Languages that are "closer to the underlying machine" - especially as far as memory management goes - generally have lower abstraction than languages that are less explicit about memory management. A local change to how a subroutine manages memory typically requires more changes to the client - i.e. the language offers a lower abstraction - in a language that's "closer to the metal", whether the language has a rich type system like Rust or a simpler type system like C, than a language that is farther away.

  • The way I understood the bit you quoted was not as a claim that more complex type system = higher abstraction level, but as a claim that a more complex type system = more options for defining/encoding interface contracts using that language. I took their comment as suggesting an alternative to the typical higher/lower-level comparison, not as an elaboration.

    As a more concrete example, the way I interpreted GP's comment is that a language that is unable to natively express/encode a tagged union/sum type/etc. in its type system would fall on the "less complex/less power to define abstractions" side of the proposed spectrum, whereas a language that is capable of such a thing would fall on the other side.

    > which includes not only the contract of the interface expressed in the type system, but also informally in the documentation

    I also feel like including informal documentation here kind of defeats the purpose of the axis GP proposes? If the desire is to compare languages based on what they can express, then allowing informal documentation to be included in the comparison renders all languages equally expressive since anything that can't be expressed in the language proper can simply be outsourced to prose.

    • But that's why the word "abstraction" is the wrong choice. The ability of a language to express detail and the ability of a language to have high abstractions are two different things, and when we talk about high and low level languages, I claim that what we intuitively mean is abstraction, not the expressivity of contracts. For example, ATS's contracts are virtually unlimited in their expressivity (it makes Rust indistinguishable from C by comparison), yet few would say it's particularly high-level. On the other hand, Scheme or even JavaScript can express few contracts, and yet are considered high level. I think that when we think of a high-level language, what we have in mind is a language where programs typically need to concern themselves with fewer details. This corresponds more with abstraction rather than "contract expressiveness".

      2 replies →