Given the following code :
exception E of int;
fun g(y) = raise E(y);
fun f(x) =
let
exception E of real;
fun z(y)= raise E(y);
in
x(3.0);
z(3)
end;
f(g);
When executing the code in SML I get :
stdIn:216.8-216.12 Error: operator and operand don't agree [literal]
operator domain: real
operand: int
in expression:
z 3
That's fine - I understand that the line z(3);
causes an error , since z
throws int
instead of real
.
But my problem is with the line x(3.0);
, why doesn't it cause an error ?
From my understanding , x
is g(y)
, then when we execute x(3.0)
we actually execute g(3.0)
, but g
throws only exceptions of type int
, but we passed to g
the value 3.0
,hence g
would throw a real
value , so it's supposed to be a violation , doesn't it ?
I'd appreciate if someone can explain why no error is happening when executing x(3.0)
.
Thanks
EDIT:
When I remove z(3);
, meaning :
- fun f(x) =
= let
= exception E of real;
= fun z(y)= raise E(y);
= in
= x(3.0)
=
= end;
val f = fn : (real -> 'a) -> 'a
- f(g);
The output is :
stdIn:11.1-11.5 Error: operator and operand don't agree [tycon mismatch]
operator domain: real -> 'Z
operand: int -> 'Y
in expression:
f g
-
So , as U can see , in both cases we'll get error .
Hence , I'm back at square one : why when both x(3.0)
and z(3)
appear (see code 1 , the first code posted at the beginning of the post) one after the other , why does SML only refers to the error that the second line (z(3);
) caused , and not to the error that
the first line caused (x(3.0);
) .
10x again
To complement Jesper's excellent answer: In other words, there is nothing wrong with the call to x
inside f
. If you remove the erroneous call to z
, and then type f
into an SML prompt, then you should see that the type system has inferred the type
(real -> 'a) -> 'a
for it. That type is perfectly fine, it is merely the call to f
later on in your program that is ill-typed. because g
does not match the parameter type real -> 'a
as required.