The author really needs to be complemented on rewriting swathes of code from Python to Haskell.
In Google, in my project, we've had runtime errors in Python code, due to wrongly spelled variables(although that is a different problem), and type error, something a compiler would have caught.
Strong type checking is something that I truly like about Haskell and OCaml, I'm reasonably convinced that once my program has passed the typechecker, it is logically correct. Though debugging in Haskell is truly a different ballgame altogether (I'm a Haskell noob).
pylint can help with misspelled variables and type errors. I started using it recently and love it. I still love my C++ compiler though and would not trade it for anything else.
pyflakes also detects typos easily, and it's quite useful.
In languages that don't catch anything you can usually still use tools for static verification.
As another example, Java may let you get NullPointerException, but FindBugs detects a lot of those.
Wow thanks, I didn't know pyflakes. I knew pylint, but will make it more of a point to run it. I only occasionally need to code in Python, but when I have to, it is legacy code that I modify.
> we've had runtime errors in Python code, due to [...]
> type error, something a compiler would have caught
Are wrongly spelled variable names and type errors the only runtime errors that you get? If not what percentage are they?
Personally, I think that people tend to obsess about the specific type of errors because the 'solution' (static-typing) is something that already exists, whereas there is not easy solution to other types of flaws.
C is statically typed, but I can still attempt to dereference a null pointer. Static typing doesn't save me here, nor does the compiler, as it's possible for these issues to happen at runtime.
This may be something that Haskell doesn't allow, but it's not something inherent to static-typing.
Intercal is dynamically typed, but it doesn't save me any development time or make my code any shorter! (Well, maybe compared to Java :)).
On top of this, the C type system is not really about correctness at all. My understanding is that it primarily helps with performance, memory management (e.g. you know the size of stuff) and not accidentally using a non-pointer as a pointer. I'm not a C person, but C does not give off a vibe of caring about correctness.
In fact, C is particularly unsafe: you can get all sorts of fun things like bus errors and segfaults that are basically impossible in other languages. C definitely has a place, but only if correctness is much less important than performance.
You can ultimately come up with a sufficiently bad language for anything.
Also, the way Haskell avoids null errors like this is with the static type system. So while it's certainly not inherent to all static type systems (then again, nothing has to be inherent to static type systems except being verified at compile time), it is a property of the type system.
I'm just 'arguing' that pitting static typing against dynamic typing using specific languages as examples isn't necessarily the whole picture. Saying that static typing will save you from attempting to call methods on None in Python is a fallacy. Saying that Haskell's static type system will save you, is possibly correct.
My original point was that it's possible that we (programmers) focus more on issues that could be with static typing (of some implementation) just because it seems like a group of problems that could be 'easily' solved. I.e. 'the grass is always greener'
Yes, probably that is my confirmation-bias at talk. But more than anything it is the frustration that the whole make into a par file and deploy it on a production system, only to find just moments later that the binary isn't up because of a typo is frustrating in any language.
If you're hoping to catch a specification error, don't use a type like `Integer -> Integer`, which doesn't capture the specification except in a most general sense.
Just as you should write good tests, that actually test for useful properties, so you should write good types -- and get useful proofs back from the compiler as a result.
I wasn't trying to catch the error of "program author is a moron who doesn't know the difference between Fibonacci and factorial". Were I trying to catch that error I would have been aware of it, and then much less likely to write the bug in the first place. This is a truism that is well accepted by testing proponents: which tests you write are incredibly important, and you need to write your tests first in order to avoid a curve fitting problem (so to speak). Any non-trivial test would have shown my function to be very broken, what type would you have used to represent that so it wouldn't compile?
Numerical algorithms suffer from a paucity of types. So either you enrich your numerical type hierarchy, or you prove an implementation matches a model, e.g. for fibonacci http://stackoverflow.com/a/8434107/83805
I don't have a response to that, other than to say, now you know why I decided to write compilers instead of pursue a graduate degree in computer science.
The point about a static type system not catching all errors is well taken[1], but if a programmer has mixed up factorial and Fibonacci I would expect that their tests would reflect this as well as their code. This is more the sort of thing you should rely on code reviews to spot.
[1] Isn't the old joke in Haskell "If your program compiles it probably does something someone would find useful, but not necessarily the useful thing you want"
It's not unreasonable, it only seems unreasonable because of the context. I've seen several really good programmers (and overall bright people) mix the implementation of the two up.
In Google, in my project, we've had runtime errors in Python code, due to wrongly spelled variables(although that is a different problem), and type error, something a compiler would have caught.
Strong type checking is something that I truly like about Haskell and OCaml, I'm reasonably convinced that once my program has passed the typechecker, it is logically correct. Though debugging in Haskell is truly a different ballgame altogether (I'm a Haskell noob).
I'll stop here lest this turns into a flame war.