Hacker News new | ask | show | jobs
by fish45 1813 days ago
> after you know one language well, you know them all instinctively

This isn't strictly true. Elixir, while functional, isn't completely pure and has a dynamic type system which definitely lowers the learning curve.

Developers who know one language well are likely equipped to pick up a language like Haskell faster than even a mathematician, but I can't imagine that a Java one trick would pick up Haskell (or APL, or Scheme, etc.) "instinctively"

2 comments

I don’t really understand how a type system in and of itself raises the learning curve unless the language commonly uses esoteric types. You still have to understand your data structures in dynamically typed languages; does it really add much cognitive overhead to declare what they are?
A common example I use is an Abstract Syntax Tree, which is essentially a mutually recursive polymorphic tree. In Elixir you might model this with a tuple labelled by an atom. With Haskell you'd use ADTs and pattern matching, which are easy to pick up because they're first class in the language but they're still something to learn. In Java, your understanding has to be a bit deeper; you'd have to learn about abstract classes. In C, you'd need to understand forward declaration and tagged unions.

Honestly I can't think of an example of anything which is harder to model in Haskell's type system, but I think the Java and C examples demonstrate that you do have to learn different type systems to model more complex examples.

I totally agree that type systems end up reducing cognitive overhead in the long run though.

A static type system often requires a deeper understanding. It won't compile if there's a small type error, by contrast the same error in a dynamic type system either doesn't exist or doesn't show up until runtime
I honestly struggle to understand what can be a « small » type error. I would be happy to read an example.

By definition, this can only happen if you use the wrong type in the wrong place : it can only be a huge bug or there is some dark magic I don’t understand.

I know a lot of langages manage to let you use strings as numbers and vice versa but I don’t see another case where you would voluntarily pass a wrong type. And this is not incompatible with string typing as long as the langage provides auto-casting.

There's a lot of intricacies that can happen. Let's say specifying an int with the wrong precision.

This can lead to a runtime error, or it can make no difference whatsoever. Enforcing that consistency in the compiler is powerful but is also another obstacle to someone who's just trying to get a simple example working.

Just because there is a type error by no means qualifies it as a huge bug. That's why JavaScript and the web stack in general is successful. It fails gracefully. Instead of a rendering a website completely unusable, an error perhaps only renders a button in the wrong place.

Contrast this with Scala, where a subtle type error refuses to build at all. If you're green, hunting down the source of that error can be very arduous.

Failing at compile time can be very powerful but it can also add another obstacle to overcome.

I understand what you mean because I come from there (started with PHP and Python more than a decade ago). So maybe it’s just a preference bias on my side but I never thought that a compiler preventing errors added difficulty. On the contrary, I remember that PHP was painful to debug when you sometimes had nothing shown in the browser, no errors at all (tbh, it’s old like maybe PHP 3 or 4) then the same thing happened in JS.

It never happened since I switched to strictly typed langages and tbh, you rarely compile type errors if you have an IDE that shows in bright red that you are wrong.

The few times last years I had to write some Python, I really felt uncomfortable and it was really hard not to make mistakes and not to trust my IDE auto completion.

My brain is now plugged on « if I write something that is not proposed, it must be red ».

But again, I understand your point and maybe it’s just me.

Imho, the type system should either be really strict and strong like in Scala or it should very loose like in TypeScript. Anything in between is just a nuisance.

Btw, there are other tools than compilers that can analyze your code for errors. Try PyCharm

Indeed. Common wisdom says that types REDUCE the cognitive overhead.
It depends a lot on the level of information you are aiming to encode in your type system. It is quite obvious that some basic types reduce cognitive overhead significantly, by helping you remember the exact data structures that you are encoding.

But once you start adding lots of details, such as trying to specify the exact type of a stable sort operation, the overhead starts increasing dramatically. Another example I really love in this area is trying to code a type-safe MxN matrix multiplication that keeps track and validates measurement units for each element in each matrix (that is, it allows a cell in the result matrix to be 0.3m^2*s, but not 0.3m^2 + 0.1m). You'll find that few libraries, even in Haskell or F#, attempt such a thing, just because the types become infuriating and obscure the linear algebra.

I find it an immense reduction in cognitive overload. You don't need to scan and understand everything surrounding a line of code to understand what's happening if you know the types.
I'm not saying you're going to be productive immediately, but the fundamentals are there and (with effort) you'll be able to get there.