标准ML中的顶级无点

时间:2017-10-14 07:44:16

标签: sml pointfree

第一个和第二个flatMap运作良好。为什么第三个不起作用?

fun flatMap f xs = List.concat(List.map f xs)
fun flatMap f = List.concat o List.map f
val flatMap = (fn mmp => List.concat o mmp) o List.map;

1 个答案:

答案 0 :(得分:1)

这是由于称为“值多态性”或“值限制”的规则。根据此规则,如果表达式可能是“扩展的”,则值声明不能创建多态绑定;也就是说,一个值声明只能创建一个多态绑定,前提是它符合严格限制的语法,确保它不能创建引用单元或异常名称。

在您的示例中,由于 (fn mmp => List.concat o mmp) o List.map 调用函数 o,因此它不是非扩展性的; 知道 o 不会创建引用单元格或异常名称,但语法无法区分。

所以声明 val flatMap = (fn mmp => List.concat o mmp) o List.map 仍然是允许的,但它不能创建多态绑定:它必须给 flatMap 一个单态类型,例如 (int -> real list) -> int list -> real list。 (注意:并非标准 ML 的所有实现都可以在所有上下文中推断出所需的类型,因此您可能需要添加显式类型提示。)

存在此限制是为了确保我们不会通过使用一种类型写入引用单元并使用不同类型读取它来隐式地从一种类型转换为另一种类型,或者通过将一种类型包装在多态异常构造函数中并展开它使用不同的类型。例如,下面的程序被值限制禁止,但如果允许,每个程序都会创建一个名为 garbage 的类型为 string 的变量,该变量是从 整数 初始化的17

val refCell : 'a option ref =
  ref NONE

val () = refCell := SOME 17

val garbage : string =
  valOf (! refCell)
val (wrap : 'a -> exn, unwrap : exn -> 'a) =
  let
    exception EXN of 'a
  in
    (fn x => EXN x, fn EXN x => x)
  end

val garbage : string =
  unwrap (wrap 17)

更多信息:

  • "ValueRestriction" in the MLton documentation
  • "Value restriction" on the English Wikipedia
  • "Types and Type Checking" in SML/NJ's guide to converting programs from Standard ML '90 to Standard ML '97。 (标准 ML '90 有这个规则的不同版本,它更宽容——它会允许你的程序——但被认为“有点微妙”,在某些情况下“令人不快”,因此它在标准 ML '97 中被替换。)< /li>
  • The Definition of Standard ML (Revised) (PDF) 的以下部分:
    • §4.7“非扩展表达式”,第 21 页,其中定义了哪些表达式被视为“非扩展”(因此可用于多态值声明)。
    • §4.8 “Closure”,第 21-22 页,它定义了使绑定多态的操作;此操作通过防止绑定变得多态(如果表达式可能是扩展的)来强制执行值限制。
    • 推理规则 (15),第 26 页,使用上述操作;另见第 27 页的评论。
    • 关于推理规则 (20) 的注释,第 27 页,解释了为什么上述操作不适用于异常声明。 (从技术上讲,这与值限制有些不同;但如果没有这个,值限制将毫无用处。)
    • §G.4“值多态性”,第 105-106 页,讨论了与标准 ML '90 相比的这一变化。