递归绑定中的 SML 语法限制? [英] SML syntactical restrictions within recursive bindings?

查看:50
本文介绍了递归绑定中的 SML 语法限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SML 的递归绑定中似乎存在语法限制,我无法理解.我在第二种情况下没有遇到的这些限制是什么(请参阅下面的来源)以及在第一种情况下使用自定义运算符时遇到的限制是什么?

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?

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

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.

错误信息让我很困惑.在我看来,最清楚的是 HaMLet 的一个,它抱怨递归值绑定中的非法表达".

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

代替:

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 语法精妙之处?它的合理性是什么?

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

推荐答案

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

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

对于rec内的每个值绑定pat = exp",exp必须是fn match".

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

严格来说,不允许有任何括号.在实践中,这很少成为问题,因为您几乎总是使用 fun 声明语法.

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.

这篇关于递归绑定中的 SML 语法限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆