News for hackers. Stuff that matters.
Re:An Overview of the Starlark Language by vlovich123 on Thursday June 06, 2024 @02:16AM (#40594089)
I don’t get this argument as it seems at odds with the existence proof of Python itself having optional typing, type inference, understandable type errors and an expressive language. What am I missing?
Re:An Overview of the Starlark Language by kccqzy on Thursday June 06, 2024 @02:31AM (#40594205)
Here's an elementary litmus test that anyone slightly experienced with type systems will know.

How do you type the omega combinator in Python?

    lambda x: x(x)
What about the application of the omega combinator to itself?

    (lambda x: x(x))(lambda x: x(x))
How do you type the Y combinator in Python?

    lambda f: (lambda x: f(x(x)))(lambda x: f(x(x)))
Depending on the choice of the type system you can either answer: this cannot be assigned a type in which case your type system is too weak to express many real-world programs, or it does have a type but then your type system is so sophisticated that people using this language (just for writing BUILD rules) won't be able to understand type errors in this type system. I have yet to find a middle ground.

In case you claim this is impractical functional programming, bear in mind you can write the same thing using classes in object-oriented programming.

---

Okay let's not even talk about these weird-looking "combinators" even though they have a rich history. Consider this function:

    lambda x: {'this': x, 'next': x + 1}
What is its type? Again the answer depends on plenty of choices that need to be made by the type system designer. Do you force dictionaries to have a single type for values? If so, many users used to Python will reject your system for being too inflexible. If not, will you now introduce row polymorphism in your type system? Will you now introduce depth subtyping and width subtyping in your type system? (For example if a function only needs field 'x' in a dictionary but the caller passes a dictionary with both fields 'x' and 'y' should not result in an error; that's why you need subtyping.) Now let's consider the lowly plus operator. In real Python the plus operator can work on integers, floats, strings, sets, etc. Let's say your type inference algorithm uses the RHS to find that x must be an integer. But that's wrong; it could still be a float. Can you now write a type for that expression? Hint: it involves record types, intersection types, type variables and other things that would not be comprehensible.
Re:An Overview of the Starlark Language by vlovich123 on Thursday June 06, 2024 @02:49AM (#40594315)
This seems like a very weird technical explanation that doesn’t actually address my question. Python typing works well in practice and doesn’t suffer from any of the problems you listed.

Also, from a brief investigation, according to [1] Haskell also isn’t able to express the omega combinator in its type system (& indeed the answer says very few type systems are able to do so). This suggests this is a very bad litmus test if almost no languages can actually pass it even though a) languages exist with explainable type errors b) the languages are general purpose and fairly expressive c) they support type inference. An obvious example of this is Rust.

[1] https://stackoverflow.com/questions/33546004/is-it-possible-...

Re:An Overview of the Starlark Language by kccqzy on Thursday June 06, 2024 @02:54AM (#40594338)
You have a different definition of "works well" and also a different definition of "type inference" here. Rust doesn't have global type inference. C++'s `auto` doesn't count. Go's `:=` syntax doesn't count.

Why not? Because you are adding typing retroactively to a dynamically typed language like Python. If a language was built with typing, you can do this because your initial choice of a type system already constrains the set of valid programs. But a Python-like language where users are already used to having no restrictions on runtime types? Absolutely not. Especially not in a language that encourages duck typing. Let's go back to the omega combinator example. The Stack Overflow link is correct: Haskell cannot assign a type to it. That means the type system is purposefully designed weak enough that the omega combinator cannot be written in the first place! No valid Haskell program has it! Therefore you can totally disregard it. Python is different. You can already write the omega combinator in it. I wrote it three times in this thread. So a bolt-on type system needs to assign a type to it. And you can't.

Python does not have a type system that "works well" and will never have one.

Re:An Overview of the Starlark Language by vlovich123 on Thursday June 06, 2024 @04:25AM (#40594933)
I think the disagreement is about what “works well” means. You are approaching it from some kind of theoretical purity whereas most people approach it from the perspective of “works for every program I am likely to encounter”. Omega combinators aren’t an example of something typically written in Python. I think you’re making a similar decision about global type inference as the only “true” definition of type inference when clearly more limited type inference already adds a significant amount of utility & there’s not typically that much lost in an inability to avoid typing functions - it’s a bit inconvenient in some places, but overall acts as a way to define the explicit contract between the method body and the rest of the code which makes errors faster to spot and the language compile more quickly.

You are correct that the holy grail you’re trying to reach is impossible, but relaxing some constraints still yields a heck of a lot of practical benefit.

Re:An Overview of the Starlark Language by tialaramex on Thursday June 06, 2024 @05:41AM (#40595437)
Global inference is a nightmare, you simply don't want global inference. It means that the minimum understandable system is the entire system, if you don't understand the entire system you don't understand any of it, this can't scale.

When weird type theory people insist you want global inference and that you should sacrifice something you actually value to get it, treat them the same as if Hannibal Lecter was explaining why you should let him kill and eat your best friend. Maybe Hannibal sincerely believes this is a good idea, that doesn't make it a good idea, it just further underscores that Hannibal is crazy.

Re:An Overview of the Starlark Language by saagarjha on Thursday June 06, 2024 @06:34AM (#40595794)
As a user of languages that do global inference, I have yet to see much killing and eating in the programs I work on. They mostly make sense.
Re:An Overview of the Starlark Language by kccqzy on Thursday June 06, 2024 @12:36PM (#40599449)
The problem with "works for every program I am likely to encounter" is that you don't know what kind of programs your users are writing.

Well, now that I think more about it, except when you are Google or Meta and you have a giant monorepo full of code that users of this language has actually written. So if Starlark were to gain a type system, the type system designer would probably just run it through the entire Starlark code at Google.

Speaking of Meta, this suddenly reminds me of Flow https://flow.org/ an effort at Meta to add a bolt-on type system to JavaScript. Naturally it doesn't aim to "work well" 100% of the time but maybe working 80% of the time is already valuable enough for them to use and announce it.

Re:An Overview of the Starlark Language by vlovich123 on Thursday June 06, 2024 @02:36PM (#40600819)
> is that you don't know what kind of programs your users are writing

Except we have lots of easily accessible OSS code available via GitHub/GitLab etc in addition to self-reporting from closed repos. Can you find any instance of an omega combinator in use? I'm not even sure omega combinator is relevant to Starlark given that Starlark is a more limited language derived from Python. For example, it doesn't typically allow for recursion which I believe would be required to express an Omega combinator within it. Yes I know the definition of the combinator says it's not recursive, but that's in a pure CS sense. In a practical sense, there's not much difference between a function being passed itself as an argument and then invoking it vs invoking itself directly, particularly from an enforcement perspective. Indeed, you can verify it'll fail the recursion prevention code in Starlark [1]

[1] https://github.com/bazelbuild/bazel/blob/e1a73e6e89a082e3d80...

Re:An Overview of the Starlark Language by yorwba on Thursday June 06, 2024 @06:59AM (#40595952)
Your dichotomy between type systems that are too restrictive and type systems that are too complex only appears because you implicitly require soundness.

In Python, all your examples can be typed as "Any" https://docs.python.org/3/library/typing.html#the-any-type

It's an extremely simple type that never leads to hard-to-understand type errors, because it never produces type errors. And you can use it for any real-world program, including malformed ones.

Of course that means the type system is unsound and accepts programs that will fail at runtime. But that is perfectly fine as long as the type checker can spot some issues and gets out of your way otherwise.

Re:An Overview of the Starlark Language by poincaredisk on Thursday June 06, 2024 @12:37PM (#40599460)
And it works great for incremental typing! You start with almost everything (except constant literals and functions that return then) having a type "Any" and let users add typing incrementally.

Python typing is so basic that it didn't even support a proper JSON type until a year ago (!), and yet it brings value to millions of Python programmers around the world.