I have this code snippet
fun decrement_to_zero r = if !r < 0
then r := 0
else while !r >= 0 do r := !r - 1
from this tutorial
https://learnxinyminutes.com/docs/standard-ml/
But I get this error:
stdIn:1.2-33.9 Error: operator and operand don't agree [literal]
operator domain: int ref
operand: int
in expression:
decrement_to_zero 10
when I call it with
- decrement_to_zero 10;
Why?
Why?
If you inspect the function's type signature,
- decrement_to_zero;
> val it = fn : int ref -> unit
you can confirm that its input type does not align with 10 : int
. But if you create an int ref
,
- val foo = ref 10;
> val foo = ref 10 : int ref
and pass this to your function,
- decrement_to_zero foo;
> val it = () : unit
you will see that the reference has been updated, but not to zero,
- foo;
> val it = ref ~1 : int ref
So the function's name was quite poorly chosen, and written. It seems that a lot has gone wrong with that tutorial since I initially wrote it.
Although Standard ML has support for references, it is often more idiomatic to write pure functions. A pure function takes only values as input and returns values as output, but does not affect the world outside of the function (such as what the reference foo
points to at any given point in time). So for example,
fun actually_decrement_to_zero n =
if n > 0 then actually_decrement_to_zero (n-1) else n
And using this,
- actually_decrement_to_zero 10;
> val it = 0 : int
As you can see, the result comes right out of the function, rather than indirectly through a reference.