SML syntactical restrictions within recursive bindings?

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-08 02:14:39

问题


There seems to be syntactical restrictions within SML's recursive bindings, which I'm unable to understand. What are these restrictions I'm not encountering in the second case (see source below) and I'm encountering when using a custom operator in the first case?

Below is the case with which I encountered the issue. It fails when I want to use a custom operator, as explained in comments. Of the major SML implementations I'm testing SML sources with, only Poly/ML accepts it as valid, and all of MLton, ML Kit and HaMLet rejects it.

Error messages are rather confusing to me. The clearest one to my eyes, is the one from HaMLet, which complains about “illegal expression within recursive value binding”.

(* A datatype to pass recursion as result and to arguments. *)

datatype 'a process = Chain of ('a -> 'a process)

(* A controlling iterator, where the item handler is
 * of type `'a -> 'a process`, so that while handling an item,
 * it's also able to return the next handler to be used, making
 * the handler less passive. *)

val rec iter =
   fn process: int -> int process =>
   fn first: int =>
   fn last: int =>
      let
         val rec step =
            fn (i: int, Chain process) (* -> unit *) =>
               if i < first then ()
               else if i = last then (process i; ())
               else if i > last then ()
               else
                  let val Chain process = process i
                  in step (i + 1, Chain process)
                  end
      in step (first, Chain process)
      end

(* An attempt to set‑up a syntax to make use of the `Chain` constructor,
 * a bit more convenient and readable. *)

val chain: unit * ('a -> 'a process) -> 'a process =
   fn (a, b) => (a; Chain b)

infixr 0 THEN
val op THEN = chain

(* A test of this syntax:
 *   - OK with Poly/ML, which displays “0-2|4-6|8-10|12-14|16-18|20”.
 *   - fails with MLton, which complains about a syntax error on line #44.
 *   - fails with ML Kit, which complains about a syntax error on line #51.
 *   - fails with HaMLet, which complains about a syntax error on line #45.
 * The clearest (while not helpful to me) message comes from HaMLet, which
 * says “illegal expression within recursive value binding”. *)

val rec process: int -> int process =
  (fn x => print (Int.toString x) THEN
  (fn x => print "-"              THEN
  (fn x => print (Int.toString x) THEN
  (fn x => print "|"              THEN
   process))))

val () = iter process 0 20
val () = print "\n"

(* Here is the same without the `THEN` operator. This one works with
 * all of Poly/ML, MLton, ML Kit and HaMLet. *)

val rec process =
   fn x =>
     (print (Int.toString x);
      Chain (fn x => (print "-";
      Chain (fn x => (print (Int.toString x);
      Chain (fn x => (print "|";
      Chain process)))))))

val () = iter process 0 20
val () = print "\n"

(* SML implementations version notes:
 *   - MLton, is the last version, built just yesterday
 *   - Poly/ML is Poly/ML 5.5.2
 *   - ML Kit is MLKit 4.3.7
 *   - HaMLet is HaMLet 2.0.0 *)

Update

I could work around the issue, but still don't understand it. If I remove the outermost parentheses, then it validates:

val rec process: int -> int process =
   fn x => print (Int.toString x) THEN
  (fn x => print "-"              THEN
  (fn x => print (Int.toString x) THEN
  (fn x => print "|"              THEN
   process)))

Instead of:

val rec process: int -> int process =
  (fn x => print (Int.toString x) THEN
  (fn x => print "-"              THEN
  (fn x => print (Int.toString x) THEN
  (fn x => print "|"              THEN
   process))))

But why is this so? An SML syntax subtlety? What's its rational?


回答1:


It's just an over-restrictive sentence in the language definition, which says:

For each value binding "pat = exp" within rec, exp must be of the form "fn match".

Strictly speaking, that doesn't allow any parentheses. In practice, that's rarely a problem, because you almost always use the fun declaration syntax anyway.



来源:https://stackoverflow.com/questions/25858856/sml-syntactical-restrictions-within-recursive-bindings

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!