> I annotated the hell out of my programs, and completely avoided OCaml's type inference as much as I could because I saw that it could not guess what I meant.
The type checker and the type inference parts of the compiler are one and the same. If the type checker can’t infer what you mean you are most likely writing invalid code.
> Error messages like "This expression is of type X but an expression was expected of type X" were not uncommon, and super frustrating.
Ocaml is a strongly typed static language. As such your code has to respect type constraints. It’s very much a feature not a bug.
Still to be less defensive I too sometimes wish the error messages were more clear in highlighting why a certain type was expected but at least Ocaml provides tooling to live check the inferred type of any sub-expression while you edit your code.
Of course I'm writing invalid code: that's why I'm getting error messages. The problem is that I'm having trouble understanding why it's invalid. Error messages are supposed to help me here, but quite often they didn't.. they just led to more confusion... especially in complex code, where I needed help and clarity most.
> Ocaml is a strongly typed static language. As such your code has to respect type constraints. It’s very much a feature not a bug.
That's reasonable if the error message were "This expression is of type X but an expression was expected of type Y". But the worst error message in the OCaml interactive toplevel is when they're the same. This happened when you defined a new type named X (which, incidentally, must be lowercase), but there were still references to things of the old type X.
I think this has been fixed in recent versions of OCaml.
You can get the same thing in Java essentially: two classes with the same name but loaded by different class loaders are incompatible. You’d get errors at runtime that you can’t cast X to X. I think they’ve made the exception messages more helpful in more recent Java versions, but in older versions the errors were very confusing to newbies because they didn’t mention the class loader difference which was the actual cause of them
In OCaml I think this could only happen with the interpreter (e.g., an interactive toplevel). At least today the compiler complains if you try to define two types with the same name in the same context.
The problem is that it would happen often in the interpreter when you were interactively trying stuff out, because when you're trying stuff out, you change the definitions of things.
Python actually sort of has the same problem not only when you use an interactive interpreter but even when you reload a module: the new class definitions don't modify the old one, they just get bound to the same name. So it's easy to end up with two alglayout.Vbox classes or two diff.Formula classes in the same interactive interpreter at the same time. But it's much less of a problem in Python because Python usually doesn't care what class things are, just what methods they define, so objects belonging to both classes can coexist peacefully. The usual exception is when you have an isinstance check somewhere.
The fact that this problem took 25 years to fix is maybe the more damning thing. It wasn't a bug, exactly; it was a usability problem. Clearer demonstrations of development priorities could hardly be given.
That was mostly a man-power issue. The good news is that nowadays such nonsensical error messages are near the top of my personal development priority for OCaml.
During those 25 years OCaml gained native-code compilers for new architectures, labeled arguments, and polymorphic variants, among other things. How could it be mostly a manpower issue?
Work and time contributed by open source collaborators on their free or academic time cannot be magically converted from one subsystem to another. It is honestly very easy to have progress on the aspects that spark interest while some subsystem are starved from attention when there are no full-time developers working on a project.
That's true, but that doesn't mean there was no manpower to fix that error message; it meant that fixing it wasn't a priority to the people who were working on OCaml at the time. You're just offering an explanation for why it wasn't a priority: fixing it didn't spark their interest.
The type checker and the type inference parts of the compiler are one and the same. If the type checker can’t infer what you mean you are most likely writing invalid code.
> Error messages like "This expression is of type X but an expression was expected of type X" were not uncommon, and super frustrating.
Ocaml is a strongly typed static language. As such your code has to respect type constraints. It’s very much a feature not a bug.
Still to be less defensive I too sometimes wish the error messages were more clear in highlighting why a certain type was expected but at least Ocaml provides tooling to live check the inferred type of any sub-expression while you edit your code.