2

I'm new to Standard ML and trying to write the following code

 fun whilestat test stmt1  = 
        (fn x => if (test x) then (stmt1 x;whilestat test stmt1 ) else (x) );

The issue is that it gives me the following error

w.sml:21.6-22.82 Error: right-hand-side of clause doesn't agree with function result type [circularity]
expression:  ('Z -> 'Y) -> 'Z -> 'Z
result type:  ('Z -> 'Y) -> 'Z
in declaration:
whilestat2 = (fn arg => (fn <pat> => <exp>))

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

Im just trying to emaulate a while condition where if the staement is true then it recurses, else returns the value.

Coder
  • 77
  • 4
  • The `uncaught exception error` indicates a bug in the code for the SML/MJ compiler itself rather than in your code (albeit one which is triggered by a bug in your code). I have encountered that bug in the past, but am pretty sure that it has since been fixed. In the version I use (110.82), I don't get that secondary error message when I run your code. – John Coleman Nov 28 '17 at 22:36

1 Answers1

7

The issue lies in the return type of whilestat. In the then branch, you return a function, whereas in the else branch, you return return an arbitrary piece of data. I think you simply forgot to pass all of the arguments when you recurse in the then branch.

Here's how I would write it (notice also that there's no need to use fn x => ..., which I think contributed to your confusion).

fun whilestat test stmt1 x =
  if test x
  then (stmt1 x; whilestat test stmt1 x)
  else x

In the future, you might find it helpful to explicitly annotate types in your source code, to double check your reasoning. I found your bug by trying to fill in the ??? below:

fun whilestat (test : 'a -> bool) (stmt1 : 'a -> unit) : ??? =
  ...
Sam Westrick
  • 1,248
  • 1
  • 7
  • 9
  • I'm not sure what you mean---`whilestat` is a higher-order function, because it takes argument(s) which are functions (in this case, `test` and `stmt1`). Perhaps it might help for you to read about a concept called _currying_. In particular, as a small example, consider that `fun f x = fn y => x + y` is equivalent to `fun f x y = x + y`. – Sam Westrick Dec 04 '17 at 02:47
  • On reflection, I suppose that any curried function is necessarily higher-order, regardless of the types of its arguments. This is because you can partially apply it to obtain a value of function type. Regardless, I do think it would be helpful for you to read about _currying_ and _partial application_. – Sam Westrick Dec 04 '17 at 02:57