Search code examples
smlsmlnj

Why am I getting "unbound variable or constructor" in my SML program


I have written a method to return the first element in a list that satisfies a function (passed in via currying). The function returns NONE or SOME depending on whether or not the element satisfies a condition. I'm using Pattern Matching However, I'm getting the dreaded error: Error: unbound variable or constructor: my_function

I'm new to SML and one of the hardest things I find is understanding the error messages. From previous experience with the message, I would think the problem is that my_function never returns, but I'm having trouble seeing the logic problem here. Can someone take a quick look and tell me the problem? Is the problem that I'm raising an error when there is no element that satisfies the input function f?

I'm interested in what's wrong and perhaps more importantly, is there any way to get more information when you see this sort of error?

val  my_function = fn f => fn lst =>  (* Notice currying *)
  case lst of
      [] => raise NoAnswer  (* Get here is nothing in lst saf

    | x::xs => case f(x) of NONE => ( my_function f xs)
                 | SOME y  =>  x 

 val test = my_function(fn x => if x < 3 then SOME x else NONE) [1,2,3,4] = 2

Thanks, Dave


Solution

  • If you declare a function with the val keyword, the function can't be defined recursively. Hence, the problem is here:

    ... NONE => ( my_function f xs) ...
    

    You can say that you want the function to be defined recursively by adding the rec keyword to the declaration.

    val rec my_function = fn f => fn list => ...
    

    Alternatively, the fun keyword is syntactic sugar for val rec. fun also includes nice syntactic sugar for currying:

    fun my_function f lst = (* This is equivalent to your first line *)
    

    Sometimes you still want to use just the val keyword and not val rec. For instance,

    val f = fn x => x + 3
    val f = fn y => f y + 4 (* f here refers to the previous declaration of f *)