If I do let f1 x = x; x+1
, compiler will complain: Warning 10: this expression should have type unit.
If I do let f2 f = f(); 5
, compiler will give val f2 : (unit -> 'a) -> int = <fun>
.
Questions
f
is a function which take unit
as parameter and returns 'a
. But if it returns 'a
, why the compiler does not give Warning 10
?Warning 10
, it means it thinks f()
returns unit
, doesn't it? Then why it give 'a
as the return type?The compiler contains modules, where the type checker is a module of a compiler and its task is type checking. Conversion from one type to another type is known as implicit if it is to be done automatically by the compiler. Implicit type conversions are also called Coercion and coercion is limited in many languages.
A compiler must check that the source program should follow the syntactic and semantic conventions of the source language and it should also check the type rules of the language. It allows the programmer to limit what types may be used in certain circumstances and assigns types to values.
Whenever you see a compiler error that says something is ambiguous it normally means that you have opened some namespaces (ie using namespace std;) and other namespaces and cout is defined in both namespaces. This means it is ambiguous, the compiler does not know which definition you mean.
In C (and in C++), any expression whether its type is numeric, pointer, etc. is considered true if the value of that expression is non-zero (i.e., has any bits turned on). Any expression with a value of zero (i.e., all bits turned off) is considered false.
If compiler does not give Warning 10, it means it thinks f() returns unit, doesn't it?
Obviously, if the compiler gives f2
the type (unit -> 'a) -> int
, that means it thinks f
returns 'a
.
What would you do in the compiler's place?
Would you warn that f2
may be applied to some functions that return non-unit results, although it may never actually be applied thus?
Would you give f2
the type (unit -> unit) -> int
and make it less useful, forcing it to be used only with functions that return ()
?
Would you invent a complicated system of postponed warnings where f2
has type (unit -> 'a) -> int
but produces an additional warning at compile-time if it is applied to a function that does not return ()
? Would you make this system work across modules (the postponed warnings of a function would have to be part of the module signatures)?
Warnings are only helpful hints, not guarantees. When in doubt, not emitting the warning is the usual solution (and nearly all compilers adopt this solution, not just the OCaml compilers).
I think this is legacy behaviour from the compiler. Use -strict-sequence
to fix it:
$ ocaml
# let f2 f = f(); 5;;
val f2 : (unit -> 'a) -> int = <fun>
But:
$ ocaml -strict-sequence
# let f2 f = f(); 5;;
val f2 : (unit -> unit) -> int = <fun>
If you use ocamlbuild
, you should put this in your _tags
file:
true: strict_sequence
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With