【问题标题】:SML syntactical restrictions within recursive bindings?递归绑定中的 SML 语法限制?
【发布时间】:2014-09-16 23:41:45
【问题描述】:

SML 的递归绑定中似乎存在语法限制,我无法理解。在第二种情况下我没有遇到哪些限制(请参阅下面的源代码),而在第一种情况下使用自定义运算符时我遇到了哪些限制?

以下是我遇到此问题的案例。当我想使用自定义运算符时它会失败,如 cmets 中所述。在我测试 SML 源的主要 ​​SML 实现中,只有 Poly/ML 接受它为有效,而所有 MLton、MLKit 和 HaMLet 都拒绝它。

错误消息让我很困惑。在我看来,最清晰的是来自 HaMLet 的那个,它抱怨“递归值绑定中的非法表达式”。

(* 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 *)

更新

我可以解决这个问题,但仍然不明白。如果我删除最外面的括号,那么它会验证:

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 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))))

但是为什么会这样呢? SML 语法的精妙之处?它的合理性是什么?

【问题讨论】:

    标签: recursion sml


    【解决方案1】:

    这只是语言定义中的一个过度限制的句子,它说:

    对于rec中的每个值绑定“pat = exp”,exp必须是“fn match em>”。

    严格来说,这不允许任何括号。实际上,这几乎不是问题,因为您几乎总是使用fun 声明语法。

    【讨论】:

    • “实际上,这很少有问题,因为无论如何你几乎总是使用fun 声明语法。”:我知道fun 的使用很普遍,但出于某些原因我避免使用它并且始终使用 valfn。还是关于fn,我觉得我正面临fn 的另一个语法问题,……这可能是未来的话题。
    猜你喜欢
    • 2020-02-07
    • 1970-01-01
    • 2015-06-19
    • 2013-01-25
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    相关资源
    最近更新 更多