Live data from Hacker News

The benefits of static typing without static typing in Python

pawelmhm.github.io

21–30 of 68 posts

Re: The benefits of static typing without static typing in Python

#21

Here's a longer article ( http://codon.com/consider-static-typing ) with more background / history about static typing and Ruby. This topic has been knocked around in Ruby-land for a while; I remember seeing Michael Edgar's LASER ( https://github.com/michaeledgar/laser ) static analysis tool including some work around optional type annotations, but seems like development there has stopped.

InfraRuby is a statically-typed Ruby (compiles to the JVM). InfraRuby code runs on Ruby interpreters without modification: http://infraruby.com/blog/why-infraruby

Re: The benefits of static typing without static typing in Python

#22
post #20

Since I unit-test the heck out of my code, this doesn't really do much for me. Unit-tests test actual values (which is where the interesting bugs come from IMO) and give me more powerful refactoring capabilities than an IDE. The real benefit I'd be looking for is the chance to give the compiler hints to speed up execution times.

I don't think this is true at all. You cannot write unit tests for all plausible values sent to your functions. If you omit manual type checking in your code or in the respective unit test, you may miss some subtle failure scenarios. Undergoing a refactor, maintenance, or change from other people (or even yourself at a later point in time) only makes this more possible.

I personally find that type safety cuts down the number of unit tests I write by half and makes refactoring work an order of magnitude easier to perform.

Re: The benefits of static typing without static typing in Python

#23
post #9
post #4

The main advantage of static typing to me is that it enables automatic refactorings. Without types, it's impossible for tools to refactor your code safely without the supervision of a human. This leads to developers being afraid of refactoring and, ultimately, code bases rot and become huge piles of spaghetti that nobody wants to touch. With a statically typed language, I'm never afraid to refactor whenever I see an…

I hear this argument a lot, and I'm sure static typing is helpful when refactoring, but I have found that nothing is as important as tests when refactoring. I'd rather refactor dynamically typed code with good test coverage than statically typed code without good tests.

The point of typing is that types are tests: they ensure logical consistency of your program, and they are checked by the compiler. This has a number of consequences.

- Some error conditions are inexpressible in your program. You cannot write classical tests to verify these, as trying to recreate the erroneous conditions will result in type errors.

- You cannot forget to "write a type" like you can forget to write a test. A type always covers all the guarantees it makes. This is especially useful when there are no tests, as you have at least some kind of helper available to you.

- Types are a form of documentation. Again, even a poorly documented, poorly named project still has types.

- Types do not make tests obsolete, but they greatly reduce the number of them you have to write and maintain.

As a result of this, most Haskell projects have abysmal test coverage compared to what you'd expect in Python or Java. Nobody would (or could!) write tests that all "instanceof" checks are covered. When you forget to implement a branch in your program, you'll get a compilation warning. When you feed a value to a well-written function, you're guaranteed to get a non-nonsense result out of it (instead of an exception). But still, you can make core changes to programs you do not understand at all - while understanding the type system in general - and have your changes work as expected.

Re: The benefits of static typing without static typing in Python

#24
post #19
post #9

Earlier quoted context omitted.

I hear this argument a lot, and I'm sure static typing is helpful when refactoring, but I have found that nothing is as important as tests when refactoring. I'd rather refactor dynamically typed code with good test coverage than statically typed code without good tests.

Types are tests. In a sufficiently strong type system, you can express constraints stronger than "returns a string" or "takes an integer". For instance, if you want to make sure that a particular function always returns a valid file descriptor, make a structure for file descriptors that just contains a single int, and give it a private constructor that can only be called by the low-level functions that call the actua…

Moreover, types are tests you don't have to write and maintain.

Re: The benefits of static typing without static typing in Python

#25
post #19
post #9

Earlier quoted context omitted.

I hear this argument a lot, and I'm sure static typing is helpful when refactoring, but I have found that nothing is as important as tests when refactoring. I'd rather refactor dynamically typed code with good test coverage than statically typed code without good tests.

Types are tests. In a sufficiently strong type system, you can express constraints stronger than "returns a string" or "takes an integer". For instance, if you want to make sure that a particular function always returns a valid file descriptor, make a structure for file descriptors that just contains a single int, and give it a private constructor that can only be called by the low-level functions that call the actua…

I completely agree. For example, dependent typing lets you create a CSV type which ensures that each row added has the same number of columns. All of this is checked AT COMPILE TIME! The best part is that it's actually easy to do. Within a day or two of looking at Idris I could figure out how to build the previously mentioned CSV type.

Really good type systems are incredibly powerful tools for testing and refactoring code.

Re: The benefits of static typing without static typing in Python

#27
post #17

Earlier quoted context omitted.

> but I have found that nothing is as important as tests when refactoring You don't need those with static types. You only need to write tests for your actual code, not things that the compiler can check for you. Manually writing code to check things the computer can test for you is a waste of developers time.

The type system only goes so far. If your refactored code calls functions that take several different parameters of the same type, you can make mistakes that the compiler won't catch.

In some sense, taking several parameters of the same type can be a code smell.

Foo(str, str, str) strikes me as somewhat suspect. I realize this isn't always avoidable, but a lot of the time it is.

Re: The benefits of static typing without static typing in Python

#28

Having type annotations that are ignored at runtime would cause problems when you interact with code without type annotations, no? PHP has a (unfortunately quite limited) set of type annotations, but the interpreter actually enforces them.

How could adding ignored type annotations cause problems? Any problems that arise would have to be there without the type annotations...?

Re: The benefits of static typing without static typing in Python

#29
What does mypy do if you make a call from code with type annotations into code without? Or vice-versa?

Has anyone ever gotten paid to add annotations to code that works?

Personally, I view type systems as like a safety line when doing work on a roof, and optional typing as having a line that might or might not be tied off.

Re: The benefits of static typing without static typing in Python

#30
post #27
post #17

Earlier quoted context omitted.

The type system only goes so far. If your refactored code calls functions that take several different parameters of the same type, you can make mistakes that the compiler won't catch.

In some sense, taking several parameters of the same type can be a code smell. Foo(str, str, str) strikes me as somewhat suspect. I realize this isn't always avoidable, but a lot of the time it is.

There are workarounds for this kind of thing. Haskell uses newtypes to wrap a value with a semantically meaningful tag. Scala has a similar concept called "value types." That means you could turn something like this:

  loginUser(String, String)
Into this:

  loginUser(Username, Password)
These aren't just type aliases. So far as the language is concerned, Username and Password are incompatible types.
Post reply on HN