Diminishing returns of static typing
Those line charts are totally made up, with arguments pulled out of thin air to support this line:<p>&gt; &quot;<i>Go reaps probably upwards of 90% of the benefits you can get from static typing</i>&quot;<p>That <i>90%</i> number is totally made up as well. I don&#x27;t see evidence that the author actually worked with Haskell, or Idris, or Agda these being the three static languages mentioned. Article is basically hyperbole.<p>If I am to pull numbers out of my ass, I would say that Go reaps only 10% of the benefits you get with static typing. This is an educated guess, because:<p>1. it gives you no way to turn a type name into a value (i.e. what you get with type classes or implicit parameters), therefore many abstractions are out of reach<p>2. no generics means you can&#x27;t abstract over higher order functions without dropping all notions of type safety<p>3. goes without saying that it has no higher kinded types, meaning that expressing abstractions over M[_] containers is impossible even with code generation<p>So there are many abstractions that Go cannot express because you lose all type safety, therefore developers simply don&#x27;t express those abstractions, resorting to copy&#x2F;pasting and writing the same freaking for-loop over and over again.<p>This is a perfect example of the Blub paradox btw. The author cannot imagine the abstractions that are impossible in Go, therefore he reaches the conclusion that the instances in which Go code succumbs to interface{} usage are acceptable.<p>&gt; &quot;<i>It requires more upfront investment in thinking about the correct types.</i>&quot;<p>This is in general a myth. In dynamic languages you still think about the <i>shape of the data</i> all the time, except that you can&#x27;t write it down, you don&#x27;t have a compiler to check it for you, you don&#x27;t have an IDE to help you, so you have to load it in your head and keep it there, which is a real PITA.<p>Of course, in OOP languages with manifest typing (e.g. Java, C#) you don&#x27;t get full type inference, which does make you think about type names. But those are lesser languages, just like Go and if you want to see what a static type system can do, then the minimum should be Haskell or OCaml.<p>&gt; &quot;<i>It increases compile times and thus the change-compile-test-repeat cycle.</i>&quot;<p>This is true, but irrelevant.<p>With a good static language you don&#x27;t need to test that often. With a good static type system you get certain guarantees, increasing your confidence in the process.<p>With a dynamic language you really, really need to run your code often, because remember, the shape of the data and the APIs are all in your head, there&#x27;s no compiler to help, so you need to validate that what you have in your head is valid, for each new line of code.<p>In other words this is an unfair comparison. With a good static language you really don&#x27;t need to run the code that often.<p>&gt; &quot;<i>It makes for a steeper learning curve.</i>&quot;<p>The actual learning is in fact the same, the curve might be steeper, but that&#x27;s only because with dynamic languages people end up being superficial about the way they work, leading to more defects and effort.<p>In the long run with a dynamic language you have to learn best practices, patterns, etc. things that you don&#x27;t necessarily need with a static type system because you don&#x27;t have the same potential for shooting yourself in the foot.<p>&gt; &quot;<i>And more often than we like to admit, the error messages a compiler will give us will decline in usefulness as the power of a type system increases.</i>&quot;<p>This is absolutely false, the more static guarantees a type system provides, the more compile time errors you get, and a compile time error will happen where the mistake is actually made, whereas a runtime error can happen far away, like a freaking butterfly effect, sometimes in production instead of crashing your build. So whenever you have the choice, always choose compile-time errors.