Search code examples
typesoperatorssmloperands

operator operand type mismatch


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?


Solution

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