Closed justhsu closed 1 year ago
The previous explanation was stated in an overly strong way, but it actually corresponds to a situation I see frequently when helping students debug code. For example, leaving the thunk out here leads to an exception, not a type error:
# OUnit2.assert_raises (Failure "") (List.hd []);;
Exception: Failure "hd".
That's because the thunk argument to assert_raises
has type 'a
, so it can be instantiated at unit -> 'b
.
I admit that won't always happen:
OUnit2.assert_raises (Failure "") (1 / 0);;
Error: This expression has type int but an expression was expected of type
unit -> 'a
Hint: Did you forget to wrap the expression using `fun () ->'?
But I'd really like to leave the old tip in the book because of how often I've had to explain this.
Perhaps it could be weakened. It used to say: "If you do, the OUnit test case will fail..." That could be changed to: "If you do, the OUnit test case might fail..."
UPDATE: Or, "If you do, and the program happens to type check, then the OUnit test case will fail...".
Ah, I see... this is because []
and List.hd []
have polymorphic type, I hadn't considered that. I was actually looking at this part because a student asked me what the tip meant, and I couldn't understand on the spot. How about we move the new tip material that I added into the main text, and restore the old tip as a tip? It seems like kind of an unusual interaction of types, which is still like a common pitfall.
Sure, that could work. Would be nice to add a forward reference for "thunk", since that comes up in a later chapter.
Previous explanation wasn't quite right: leaving the function out doesn't lead to an exception, it leads to a type error.