A type system for RCL, part 2: The type system
Ruud van Asseldonk introduces RCL, a JSON extension with a strong type system. RCL enforces type safety, supports static and gradual typing, and addresses challenges like covariance to balance usability and error reporting.
Read original articleRuud van Asseldonk introduces RCL, a configuration language extending JSON, focusing on its type system. The type system in RCL is strongly typed, not converting between data types implicitly, ensuring type errors are caught early. RCL's type system includes foundation elements like types constraining values, type inference being forward-only, and a lattice structure for types. RCL supports static and gradual typing, enforcing type annotations but deferring some checks to runtime. The subtype check in RCL ensures expressions fit expected types, with a generalized subtype check handling inconclusive cases by inserting runtime checks. Variance in RCL, particularly for generic types like List[T], is discussed, highlighting how covariance is respected in the subtype check. The bottom-up inference in RCL allows for syntax-directed type inference, determining types based on context. Ruud acknowledges challenges in the type system, particularly regarding covariance, aiming for a balance between static error reporting and practical usability. The article emphasizes the importance of a strong underlying principle in designing the type system to ensure RCL remains easy to reason about.
Related
My experience crafting an interpreter with Rust (2021)
Manuel Cerón details creating an interpreter with Rust, transitioning from Clojure. Leveraging Rust's safety features, he faced challenges with closures and classes, optimizing code for performance while balancing safety.
A reckless introduction to Hindley-Milner type inference (2019)
Hindley-Milner type inference balances expressiveness and legibility in programming languages like Elm and Haskell. It enhances correctness by enforcing strict type checking, limiting coding practices for improved type safety.
First Class Contexts – Rye Language
Rye Language introduces first-class contexts for scoping Rye words, creating parent-child relationships. Context paths access values, restricting direct changes for control. Evaluation and isolation mechanisms enhance structured code organization.
I Probably Hate Writing Code in Your Favorite Language
The author critiques popular programming languages like Python and Java, favoring Elixir and Haskell for immutability and functional programming benefits. They emphasize personal language preferences for hobby projects, not sparking conflict.
Rye Language
Rye Language is a high-level, dynamic programming language emphasizing interactive use, backend development, and information processing. It supports various functionalities, runs on multiple platforms, and promotes user-friendly information manipulation with strict design principles.
However for a configuration language that is type checked and immediately run, there's not much difference between runtime type checks and pre-run static type checks. Given this escape hatch, I think the author is right to simply defer everything that cannot be checked statically into runtime checks.
Consider, for example, the given example
let a: Int = 1
let b: Any = a
let c: Int = b
In this simple case, it seems like everything works fine. But what if instead of `b = a` we had `b = foo()`? Now all the sudden discovering whether or not `b` can be safely assigned to an `Int` depends entirely on what `Foo` returns. If foo returns `Any` then you can have a mess where some refactoring ends up having a hard to detect bug.Consider, for example if foo is changed from
foo() { return 1 }
to foo() { if(bar) return "a" else return 1 }
That could be fine given foo is already sending back `Any` but now when `bar` is true that string returned could cause a runtime exception far from where `foo` was defined.To me, this seems like giving up a large portion of the benefits of having typing in the first place.
Dart 1.0 had a similar system with "optional typing" which was ultimately axed because of issues like these [1]. In my view, this sort of type system is `Any` creating optional typing.
[1] https://news.dartlang.org/2017/06/a-stronger-dart-for-everyo...
It's interesting that type checking happens at runtime so there is no compile time, only runtime. It seems this would make it acceptable. But I wonder if the assumption will always hold.
The assumption:
> The program doesn’t even have any inputs: all parameters are “hard-coded” into it. [1]
Will that always hold? What about environment variables? If the language ever needs to handle parameters, this assumption breaks and thus compile time and runtime will be separated.
Other languages like Go would force you to insert type assertion which is the same thing just explicit. I forces you to "approve" what's happening, and that's a good thing.
There is the saying that every configuration language will eventually evolve into a full blown programming language. I guess it's all about the real world proving the underlying assumptions to be incorrect.
[1] - https://ruudvanasseldonk.com/2024/a-type-system-for-rcl-part...
Related
My experience crafting an interpreter with Rust (2021)
Manuel Cerón details creating an interpreter with Rust, transitioning from Clojure. Leveraging Rust's safety features, he faced challenges with closures and classes, optimizing code for performance while balancing safety.
A reckless introduction to Hindley-Milner type inference (2019)
Hindley-Milner type inference balances expressiveness and legibility in programming languages like Elm and Haskell. It enhances correctness by enforcing strict type checking, limiting coding practices for improved type safety.
First Class Contexts – Rye Language
Rye Language introduces first-class contexts for scoping Rye words, creating parent-child relationships. Context paths access values, restricting direct changes for control. Evaluation and isolation mechanisms enhance structured code organization.
I Probably Hate Writing Code in Your Favorite Language
The author critiques popular programming languages like Python and Java, favoring Elixir and Haskell for immutability and functional programming benefits. They emphasize personal language preferences for hobby projects, not sparking conflict.
Rye Language
Rye Language is a high-level, dynamic programming language emphasizing interactive use, backend development, and information processing. It supports various functionalities, runs on multiple platforms, and promotes user-friendly information manipulation with strict design principles.