Live data from Hacker News

Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

blog.edward-li.com

141–150 of 166 posts

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#141
post #92

Earlier quoted context omitted.

As the author of that post, I'd like to point out the example was meant to be stupid. The purpose was to show different ideologies and expectations on the same code don't work, such as strict backwards compatibilities, duck typing, and strictly following linting or type hinting rules (due to some arbitrary enforcement). Although re-reading it now I wish I'd spent more than an evening working on it, it's full of issue…

> Following the general stupidness of the post: they are now unable to do that because a security consultant said they have to enable and can not break RUFF rule ANN401: https://docs.astral.sh/ruff/rules/any-type/ Okay, then your function which is extremely generic and needs to support 25 different use cases needs to have an insane type definition which covers all 25 use cases. This isn't an indictment of the type sy…

[deleted]

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#142
post #92

Earlier quoted context omitted.

As the author of that post, I'd like to point out the example was meant to be stupid. The purpose was to show different ideologies and expectations on the same code don't work, such as strict backwards compatibilities, duck typing, and strictly following linting or type hinting rules (due to some arbitrary enforcement). Although re-reading it now I wish I'd spent more than an evening working on it, it's full of issue…

> Following the general stupidness of the post: they are now unable to do that because a security consultant said they have to enable and can not break RUFF rule ANN401: https://docs.astral.sh/ruff/rules/any-type/ Okay, then your function which is extremely generic and needs to support 25 different use cases needs to have an insane type definition which covers all 25 use cases. This isn't an indictment of the type sy…

> Don't write functions that support hundreds of input data types

But by it's nature, duck typing supports an unbounded number of input types and is what Python was built on.

You've already decided duck typing is wrong and strict type adherence is correct, which is fine, but that doesn't fit the vast history of Python code, or in fact many of the core Python libraries.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#143

Earlier quoted context omitted.

As the author of that post, I'd like to point out the example was meant to be stupid. The purpose was to show different ideologies and expectations on the same code don't work, such as strict backwards compatibilities, duck typing, and strictly following linting or type hinting rules (due to some arbitrary enforcement). Although re-reading it now I wish I'd spent more than an evening working on it, it's full of issue…

Stupid is okay. _Nonsense_ is not. Your example was nonsense, it was absurd. The moment I saw the first example I was like, this should be add_ints and should only take ints. Imagine I say "the human body is dumb! Here's an example: if I stab myself, it bleeds!" Like is that stupid or absurd?

And yet, some Python users insistent on type hinting very dynamic Python code while trying to keep how dynamic it is.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#145
post #77

I am not well versed in python programming, this is just my opinion as an outsider. For anyone interested in using these tools, I suggest reading the following: https://www.reddit.com/r/Python/comments/10zdidm/why_type_hi... That post should probably be taken lightly, but I think that the goal there is to understand that even with the best typing tools, you will have troubles, unless you start by establishing good pr…

The top comment in that post shuts down the whole nonsense pretty quickly and firmly: > If you have a super-generic function like that and type hinting enforced, you just use Any and don't care about it. It's a stupid example, but even within the context of a `slow_add` function in a library: maybe the author originally never even thought people would pass in non-numeric values, so in the next version update instead…

One thing that post does do though is very clearly highlight the difference between Python's type system and say ... TypeScript's.

TypeScript's goal is to take a language with an unhinged duck type system that allows people to do terrible things and then allow you to codify and lock in all of those behaviours exactly as they're used.

Mypy (and since it was written by GVM and codified in the stdlib by extension Python and all other typecheckers)'s goal is to take a language with an unhinged duck type system that allows people to do terrible things and then pretend that isn't the case and enforce strict academic rules and behaviours that don't particularly care about how real people write code and interact with libraries.

If you include type hints from the very beginning than you are forced to use the very limited subset of behaviours that mypy allow you to codify and everything will be "fine".

If you try to add type hints to a mature project, you will scream with frustration as you discover how many parts of the codebase literally cannot be represented in the extremely limited type system.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#146
post #8

Earlier quoted context omitted.

Gradual typing means that an implicit "any" (unknown type) anywhere in your code base is not an error or even a warning. Even in critical code you thought was fully typed. Where you mistakenly introduce a type bug and due to some syntax or inference limits the type checker unexpectedly loses the plot and tells you confidently "no problems in this file!" I get where they're coming from, but the endgame was a huge issu…

> Gradual typing means that an implicit "any" (unknown type) anywhere in your code base is not an error or even a warning. That depends on the implementation of gradual typing. Elixir implements gradual set-theoretic types where dynamic types are a range of existing types and can be refined for typing violations. Here is a trivial example: def example(x) do {Integer.to_string(x), Atom.to_string(x)} end Since the func…

ty also implements gradual set-theoretic types, and can represent "ranged" dynamic types (as intersections or unions with Any/Unknown). We don't currently refine dynamic type based on all uses, as suggested here, though we've considered something very much like this for invariant generics.

In your example, wouldn't `none()` be a type for `x` that satisfies both `Integer.to_string(x)` and `Atom.to_string(x)`? Or do you special-case `none()` and error if it occurs?

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#147
post #8

Earlier quoted context omitted.

Gradual typing means that an implicit "any" (unknown type) anywhere in your code base is not an error or even a warning. Even in critical code you thought was fully typed. Where you mistakenly introduce a type bug and due to some syntax or inference limits the type checker unexpectedly loses the plot and tells you confidently "no problems in this file!" I get where they're coming from, but the endgame was a huge issu…

> Gradual typing means that an implicit "any" (unknown type) anywhere in your code base is not an error or even a warning. That depends on the implementation of gradual typing. Elixir implements gradual set-theoretic types where dynamic types are a range of existing types and can be refined for typing violations. Here is a trivial example: def example(x) do {Integer.to_string(x), Atom.to_string(x)} end Since the func…

How is this function definition (or maybe just its parameter x) "untyped"? There is enough information to deduce that the type of parameter x is empty and the type of the function doesn't matter because there is an error.

If the body of the function contained only the first or the second call, the verdict would have been that x is respectively an Integer or an Atom and the type of the function is the type of the contained expression.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#148
post #127
post #68

Earlier quoted context omitted.

I don't see why AI hype means more Python code. State of the art AI models are all closed source and accessible through an API anyways. APIs that any language can easily access. AAa for AI model development in itself, yes it's mostly Pyython, but niche.

I think you are underestimating the massive amounts of Python code that is built around these things. Also, a lot of businesses are not really interested in using an API for an LLM, instead they will modify and fine-tune their own models and deploy in their own data-centers (virtual or physical), and that means even more Python code. Sure, a system that only relies on token factory LLM APIs can be written in any lang…

> Also, a lot of businesses are not really interested in using an API for an LLM, instead they will modify and fine-tune their own models and deploy in their own data-centers

You realize model training cost millions right? "a lot of businesses" doesn't pass sniff test here.

I'm not even counting the large swaths of data required to train. And the expensive specialists.

And then you'll have to retrain outdated models every so often.

There's a reason that AI has only a handful of players delivering SoTA models and these players are all worth $5B+.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#149
post #92

Earlier quoted context omitted.

> Following the general stupidness of the post: they are now unable to do that because a security consultant said they have to enable and can not break RUFF rule ANN401: https://docs.astral.sh/ruff/rules/any-type/ Okay, then your function which is extremely generic and needs to support 25 different use cases needs to have an insane type definition which covers all 25 use cases. This isn't an indictment of the type sy…

> Don't write functions that support hundreds of input data types But by it's nature, duck typing supports an unbounded number of input types and is what Python was built on. You've already decided duck typing is wrong and strict type adherence is correct, which is fine, but that doesn't fit the vast history of Python code, or in fact many of the core Python libraries.

> But by it's nature, duck typing supports an unbounded number of input types and is what Python was built on.

You're trying to shove a square peg into a round hole. It's not about right or wrong. Either you want your function to operate on any type, attempt to add the two values (or perform any operation which may or may not be supported, i.e. duck typing), and throw an runtime error if it doesn't work--in which case you can leave it untyped or use `Any`--or you want stronger type safety guarantees so you can validate before runtime that nobody is calling your method with incorrect arguments, in which case you have to represent the types which you accept somehow.

If you want to have a method that's fully duck typed, you're supposed to use `Any`. That's exactly why it exists. Inventing contrived scenarios about how you can't use `Any` is missing the point. It's like complaining C doesn't work if you're not allowed to use pointers.

You're right that historically Python code was written with duck typing in mind, but now even highly flexible libraries like Pandas have type definition support. The ecosystem is way different from even 5-6 years ago, I can't think of any well-known libraries which don't have good typing support by now.

Re: Pyrefly vs. Ty: Comparing Python's two new Rust-based type checkers

#150

Earlier quoted context omitted.

> I am strongly against ty behaviour here. [ty developer here] Please note that ty is not complete! In this particular example, we are tripped up because ty does not do anything clever to infer the type of a list literal. We just infer `list[Unknown]` as a placeholder, regardless of what elements are present. `Unknown` is a gradual type (just like `Any`), and so the `append` call succeeds because every type is assign…

Have you all looked at how Pyrefly does it, or are your methods incompatible?

Well ours is not yet implemented, so it's too early to say whether they're compatible. :-)

But less snarkily, we do talk to them often (and the authors of other tools like mypy and pyright) to make sure we aren't introducing gross incompatibilities between the different type checkers. When there are inconsistencies, we want to make sure they are mindful rather than accidental; for good reasons; spec-compliant; and well documented.

Post reply on HN