Everybody's always fixing bugs. Static typing makes it more likely that the bugs you're working on are closer to the problem domain, instead of being crap work that should have been caught at compilation time with better languages and compilers.
Everybody's always fixing bugs. Static typing makes it more likely that the bugs you're working on are closer to the problem domain, instead of being crap work that should have been caught at compilation time with better languages and compilers.
That's a good question. But enforcing your codebase to be a Rubix cube you have to twist and turn until the static type checker says Yes is not trivial. Its a tax.
The real question is whether that tax is worth it when your goal is purely business delivery and not something else (eg, intellectual stimulation). Is it?
Writing unit tests and code review are other means to root out bugs. But they also come with a tax. When are they worth the tax and when are they not worth the tax?
In some cases we judge they are. In other cases not.
A statically typed language typically asks us to turn off our brain and apply type verification everywhere. In this way, statically typed languages wield type verification more like a religion than a tool.
In my experience NPEs are the easiest bugs to root out and fix.
Of course, the cost outweighs the benefit in this case for most industry software that can afford a few bugs at the extreme expense of (this kind of) code review.
Now the question is: are the static verification methods you're using (null-checking, type-checking, range-checking, what-have-you) worth the effort it takes to apply them over time?
And if you say yes, do you believe they are so worth it that they should be applied across your codebase always, without discretion? Most static programming languages force you (or make it hard for you not) to do this verification across the board.
Yes, actually, I don't find these things to be a particularly high burden, and the benefit, in my experience, easily outweighs it.
When you're writing code, you have to think about what kinds of things will be passed to a given function, whether the compiler checks it or not. So I find having the compiler check mundane things like this lowers my cognitive load, because I don't have to worry so much about what to do if I get a null (fail, handle it in some way, etc.).
I will agree, though, that the style of programming with maps so prevalent in Clojure makes a lot of sense in some programs. However, even then, there is a typing discipline that fits (row types).
But.
I have built plenty of large software systems. And the source of cost in those systems is always -- by at least a factor of a 100 -- was coupling and imprecise semantics.
These two problems are a function of the experience and training (and value system) of the programmer building them, and programming languages can do very little to save a system from these plights. (It might be that a static programming language can help here inasmuch as it slows down the programmer from producing too much code, but I realize that's arguable and also that I'm making a wicked joke.)
Still.
All computers ask is for semantic precision and you don't need a static type verification to get precision. So clearly static type verification is unnecessary for producing programs that work. And clearly statically-typed everywhere PLs are asking the programmer to do extra work. That's prima facie true. So the burden is really on the MLer/Haskeller to prove that that extra work is giving overall delivery throughput to the programming team. Maybe it is, maybe it isn't. But I'm waiting for the clearly thought out justification. Haven't heard it yet.
I'm not convinced this is entirely true. The kinds of information that you encode in types is the kind of information that's useful to anyone reading the code. And if that information isn't written down somewhere, then the person reading the code (maybe you sometime later) has to reconstruct it themselves. And if it's useful to write that kind of information down, why not have the computer check that it's consistent?
That's a bit contrived. No matter which language you write in, at some step a type check will happen. For dynamic types its at runtime and for static types its at compile time.
> And clearly statically-typed everywhere PLs are asking the programmer to do extra work. That's prima facie true. So the burden is really on the MLer/Haskeller to prove that that extra work is giving overall delivery throughput to the programming team. Maybe it is, maybe it isn't. But I'm waiting for the clearly thought out justification. Haven't heard it yet.
Here are just a few of the real world accounts of using Haskell in production, you can check out:
- The Joy and Agony of Haskell in Production: http://www.stephendiehl.com/posts/production.html
- Haskell is Not For Production and Other Tales: https://www.youtube.com/watch?v=mlTO510zO78
- Production Haskell - Reid Draper: https://www.youtube.com/watch?v=AZQLkkDXy68
If these didn't convince you, there are tons of Haskellers that will attest that the type system in the long run has quite substantial benefits.
This is a wonderfully, astonishingly, gobsmackingly interesting comment for me to read! In my experience of large systems (Haskell-style) types are exactly the thing you need to tame coupling and imprecise semantics.
To take one arbitrary but notable example, in a previous job we found several bugs in large industry XML schema^ by converting the schema to Haskell types and noticing, via type errors, that some things didn't match up.
^I forget if the bugs were in the schema itself or in the Java implementation that another team was using. I think a little bit of the former and a lot of the latter.
One thing I find interesting about this is that a good type system, combined with something like OCaml's module system, is that you can force decoupling. In OCaml, you can create an abstract type, which cannot be used in any way that isn't specified through the interface. You don't have to wrap the runtime value in anything, it's purely a compile time abstraction.
Yes!
> And if you say yes, do you believe they are so worth it that they should be applied across your codebase always, without discretion?
Oh god yes! Simple Hindley-Milner typing is so cheap to use it's almost free!
> Most static programming languages force you (or make it hard for you not) to do this verification across the board.
Well, not really. In Haskell, for better or for worse, you can still use `fromJust` even if it is considered rather naughty.
No, it doesn't.
People are not using Haskell because they want to turn off their brain.
A statically typed language typically asks us to redirect our brains from asking the question, "Is type verification really needed in this particular instance to deliver my business value?" to instead solving the type-checker puzzle du jour.
It's true that choosing to use a static language without a dynamic escape valve for a component constitutes making the decision that, for the pieces of that component, dynamic freedom isn't an option that needs further considered.
[1] Just like having experience in editor shortcuts bear an initial cost to make you more productive forever...
There is no such thing as type checker puzzle once you have learned types, just like you don't stop on each word once you're literate.
Your analogy doesn't apply.
I can read a book in O(n) time, where n is the number of words in the book. I can read a single word in O(1) time.
When I get a type error, that is not a O(1) fix. The type error is connected to my program in the large and I have to understand/process more than just the single line where the error is called out. The worst case, obviously, is O(n).
> Your analogy doesn't apply.
One would think I am well placed to describe my own experience of interacting with a type system.
Static type checking also significantly complicated meta programming, macros and code generation.
But hey I like statically typed languages too. A big fan of Swift which has borrowed many functional ideas. I just don't think static typing is the silver bullet that many of its proponents think.
It works well for some problems, but not all. E.g. I can't think of any statically typed language which can compete with Julia for numerical work and data science.
Haskell e.g. is just terrible at doing numerical work, as it poor at mutation. You can work effectively with lots of big matrices if you don't allow easy access to mutation.
I fail to see this as a problem. It's pretty much a feature, just as you don't expect object oriented languages to tolerate any shit you throw at them when you use the OO model.
> I just don't think static typing is the silver bullet that many of its proponents think.
You're the one making the case here, before answering it.
> Haskell e.g. is just terrible at doing numerical work
I've had good experience with https://wiki.haskell.org/Numeric_Haskell:_A_Repa_Tutorial
Perhaps you could give us an example of code you want to write that doesn't pass the type checker.
We already know about the case of maps, but it's been pointed out that is solved by row types. A different example would be good.
A statically typed language can allow us to use dynamic typing if we want. For example, using a map of variants as a query result. Programming with maps of variants is even perfectly possible and pleasant in Haskell. Dynamic typing is not unique to dynamic languages!
After becoming familiar with the code base or library, particularly with modern IDE's it's rarely taken more than 10 seconds to choose a type. When reading another person's code, it does take some time to map out the relationship between the classes, but unless your code is in one giant file/function/object you're going to have to figure that out anyway.
Rich has had many years of experience in statically typed language.
It would be just as unfair if one were to claim that dynamic typing is bad because assembly language tends to be buggy and expensive to maintain.
In fact, outside of Clojure, I've never liked a dynamic language (and I've used a few professionally).
So, I'm someone with plenty of static-language experience, and I am in the boat that types are more complicated, in some ways. Just today, I had to figure out how to wrangle TypeScript into a shape I needed (and wound up with a solution that I didn't like but which got me past the compiler errors and on to more important work). There is a cost. There is also a benefit. So the question is, what does the cost/benefit analysis yield?
Regardless, Clojure is worth learning. It's an amazing language.
It would be really interesting, and indeed probably the most valuable contribution to this whole discussion, if you could write up what the problem was and why it wouldn't have occurred in Clojure!
However this is mostly down to me being lazy and not bothering to write tests.
I've spend some time with Haskell, and tried writing some code for a simple geometry library in Haskell. Quite cool language, but I could write the same code in much fewer lines in Julia and much faster.
Haskell has just too much mental overhead. It requires far more investment than other languages to learn and I've learned plenty. Nothing has required as much effort as Haskell. Despite the effort I never felt like I could write any real and practical programs with it.
I honestly think the Haskell fan club is slightly deluded. If Haskell was truly as amazing as they think, we ought to have seen a lot more amazing software being made in Haskell. We don't. Far more interesting things seems to have been done in newer languages such as Go, Rust, Swift and Julia. That ought to be a hint that Haskell isn't quite the silver bullet that the fan club thinks it is.
This is indeed where statically typed languages come in to shine - refactoring and maintenance. With a powerful type system you can be much more assured that your refactors or small/big changes here and there don't break the whole system or unexercised parts of it.
> It requires far more investment than other languages to learn and I've learned plenty. Nothing has required as much effort as Haskell. Despite the effort I never felt like I could write any real and practical programs with it.
That's often attributed to the fact that Haskell isn't just another syntax slapped on an Algol-like language. It's not just different syntax (ML-style), but an entirely different approach to programming. This often leaves experienced programmers frustrated with the experience that they are starting from scratch (without realising that, that is what they are doing).
Some nice advice is giving by Gabriel Gonzales here http://www.haskellforall.com/2017/10/advice-for-haskell-begi....
> I honestly think the Haskell fan club is slightly deluded. If Haskell was truly as amazing as they think, we ought to have seen a lot more amazing software being made in Haskell
We have a lot of amazing software in Haskell already, e.g. Facebooks Haxl, Pandoc, QuickCheck, Yesod, Servant and many more.
The argument that Haskell isn't doing stuff right because we don't see it everywhere is quite silly. By that metric PHP would be the best designed language ever...