Search code examples
exceptionprogramming-languagesfunctional-programmingsmlsmlnj

SML - static scope doesn't cause any error while using exceptions


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


Solution

  • 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.