I am having this mysterious problem. I have this function in a file:
fun sum _ nil acc = (Real.fromInt acc)
| sum x (hd::tl) acc =
if x=hd orelse toUpper x=hd then sum x tl (acc+1)
else sum x tl acc
Now, when I run the interpreter (SMLNJ) the use the file:
use "xxx.sml";
it is working perfectly and it accepts the function as it should:
val sum = fn : char -> char list -> int -> real
But when I first open the Real signature in my file:
open Real
fun sum _ nil acc = (fromInt acc)
| sum x (hd::tl) acc =
if x=hd orelse toUpper x=hd then sum x tl (acc+1)
else sum x tl acc
it stops working and throws this error:
[opening temp2.sml]
xxx.sml:10.49-10.54 Error: operator and operand don't agree [overload conflict]
operator domain: real * real
operand: real * [int ty]
in expression:
acc + 1
xxx.sml:8.5-11.23 Error: types of rules don't agree [tycon mismatch]
earlier rule(s): char * char list * int -> real
this rule: char * char list * real -> 'Z
in rule:
(x,:: (hd,tl),acc) =>
if (x = hd) orelse (toUpper <exp> = hd)
then ((sum <exp>) tl) (acc + 1)
else ((sum <exp>) tl) acc
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:292.17-292.20
First thing that seems mysterious here is that the interpreter does not show opening Real etc etc when I type use "xxx.sml"; But, what is even more mysterious is that even if I write Real.fromInt acc inside the first rule of the function (while the Real signature is open) it still refuses to work. Could someone please help me with this because it would be great if I could have the Real signature open for the whole program.
The Real
structure implements +
with type real * real -> real
.
You use this operator on your acc
argument, so it is inferred to be of type real
. But you also apply the Real.fromInt
function with type int -> real
to acc
so from that it infers that acc
must be an int
.
Thus your type mismatch.
You have seen firsthand now that opening structures can have unintended side-effects. Avoiding these is a big part of why we organize code into structures. Opening it may seem like a convenience, but it comes with a price.