As for the error messages requiring expertise in type theory, it sounds as an exaggeration, esp. when not using advanced features.
As for the error messages requiring expertise in type theory, it sounds as an exaggeration, esp. when not using advanced features.
I don't know much about type theory but I did eventually manage to learn to interpret OCaml's type errors well enough to get things to compile. It still feels like driving a car by scraping it along a highway guardrail but it's often better than testing. I have to write twice as much code as in Python, it takes me longer to get it to run, and I still can't call it from C or Lua, but it runs twenty times as fast as Python and the process of thinking through the types helps me a lot to write code that works.
I keep hoping I'll internalize the type system enough that my programs run the first time they way they do in Python, but it hasn't happened yet.
I still often write a prototype in Python, though.
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. I still had tons of problems understanding the error messages.
Error messages like "This expression is of type X but an expression was expected of type X" were not uncommon, and super frustrating.
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.
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.
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.
That particular error message has been gone from OCaml for years now.
With experience, I am more or less able to preemptively add the annotations that will probably help (e.g. aiming avoid accidentally polymorphic functions, the return type of mutually recursive functions, etc.).
I don't think I have ever gotten "This expression is of type X but an expression was expected of type X" outside of the toplevel with type re-definitions, and recent OCaml versions have a nice error message for this now:
Error: This expression has type t/1 but an expression was expected of type
t/2
Hint: The type t has been defined multiple times in this toplevel
session. Some toplevel values still refer to old versions of this
type. Did you try to redefine them?
In general the error messages have been continuously improving in recent years.