Js is Weird in Ocaml
# true + false;; Error: This expression has type bool but an expression was expected of type int
First question is a type error. The
+ operator isn’t defined for boolean values. The perhaps mathematically valid solution is to take
true is converted into a number,
false is converted into a number
0, and then these are added up.
# List.length [;;;];; Error: Syntax error
This isn’t even valid OCaml, because the list entries must have some value. You could use something like
[();();()] if you wanted. In JS, this outputs
# [1;2;3] + [4;5;6];; Error: This expression has type 'a list but an expression was expected of type int
Invalid in OCaml. You can’t use a sum on lists. There’s another operator, which does the job:
# [1;2;3] @ [4;5;6];; - : int list = [1; 2; 3; 4; 5; 6]
In languages with types, you often have specialized operators for different kinds of operations on different types. That way, you eliminate programming errors in the code, because the programmer has to explicitly ask for a given kind of operation when they need it.
# 0.1 +. 0.2 = 0.3;; - : bool = false
First point where JS and OCaml will agree. The reason is that OCaml has a bug in the specification of floating point values because it allows them to be compared for equality. Standard ML doesn’t:
Poly/ML 5.7.1 Release > 0.1 + 0.2 = 0.3; poly: : error: Type error in function application. Function: = : ''a * ''a -> bool Argument: (0.1 + 0.2, 0.3) : real * real Reason: Can't unify ''a to real (Requires equality type) Found near 0.1 + 0.2 = 0.3
Comparisons of floating point values must use tolerances. You have to check if the two values are within each other by some small epsilon.
# 10,2;; - : int * int = (10, 2)
# not (not "");; Error: This expression has type string but an expression was expected of type bool
# +(not (not ));; Error: This variant expression is expected to have type bool The constructor  does not belong to type bool
+!! converts by first converting
 to it’s boolean representation, which is
true, then converting
true to a number due to the
+, which is
# not (not (not true));; - : bool = false
# true = "true";; Error: This expression has type string but an expression was expected of type bool
You are not allowed to compare values from different types because normal equality is homogeneous. You can make systems with heterogenous equality, but this is most often used in the case where you have some evidence the types are really the same. You then present such evidence to the type system so it can verify it. It’s a more lenient form of equality, but it’s doesn’t allow you to cheat.
true converts into
"true" converts into
NaN. After which falsity is obtained.
# 010 - 03;; - : int = 7 # 0o10 - 0o3;; - : int = 5
0 yields an octal number.
# "" - - "";; Error: This expression has type string but an expression was expected of type int
OCaml uses the type system to eliminate nonsense, yet again.
# type null = Null;; type null = Null # Null + 0;; Error: This expression has type null but an expression was expected of type int
OCaml has no null value, but we can create a null value as a new type. Clearly, the addition is ill-typed, so the compiler rejects this nonsense.
# 0 / 0;; Exception: Division_by_zero. utop # 0. /. 0.;; - : float = nan
nan represents an illegal number value. This can be useful in some situations, particularly when your data is incomplete, where you can use a
nan to represent lack of data.
It’s also useful for performance reasons. Run your computation to the end, then check for
nan. If present, the computation is failed and you can analyze why. This avoids the code to check for legality in each step, greatly improving performance for computations.
# 1/0 > 10**1000;; Error: This expression has type int but an expression was expected of type float Hint: Did you mean `10.'? utop # 1. /. 0. > 10. ** 1000.;; - : bool = false
Again, like the Q13, this is a consequence of how IEEE 754 floating point values work. Both values convert to
# true++;; Error: Syntax error
# "" - 1;; Error: This expression has type string but an expression was expected of type int
0, and then returns
-1. How can people work with this in practice?
Q17 + Q18 + Q19
All of these questions behave the same:
# (Null - 0) + "0", true + ("true" - 0), (not 5) + (not 5);; Error: This expression has type null but an expression was expected of type int
OCaml only ever reports the first error encountered. But the other expressions are not well-typed either.
utop #  + ;; Error: This expression has type 'a list but an expression was expected of type int #  @ ;; - : 'a list = 
toString, so the result is
"" + "" which is
# nan = nan;; - : bool = false
This is a consequence of IEEE 754 floating point numbers. NaN values are never equal.
# nan +. 1.;; - : float = nan
IEEE 754 again. NaN sort of represents the failed computation, so if part of the computation is a failure, then so is any further computation with that value.
# type undefined = Undef;; type undefined = Undef utop # Undef + false;; Error: This expression has type undefined but an expression was expected of type int
Another simple type error in OCaml.
# +0 = -0;; - : bool = true utop # +0. = -0.;; - : bool = true
It’s important to note that in IEEE 754, the values
-0. have different bit representations because the sign bit is flipped. This is why they can compare unequal in some cases. However, as a rule, you should never compare floating point values for equality.
# - "" + + "1" * Null - [,];; Error: Syntax error
In the lucky case, the error then makes some part of the system into nonsense and it breaks. Debugging will take time because you have to backtrack to where the fault really happened, but at least you have an error to work with.
In the unlucky case, the program will run. It will compute the wrong value. It will write the wrong value to disk. It will do this for several months and nobody will notice. Then all of a sudden, someone notices and you have months worth of data which were wrong.