Exception 价值多态性与;“生成异常”;

Exception 价值多态性与;“生成异常”;,exception,language-lawyer,sml,value-restriction,Exception,Language Lawyer,Sml,Value Restriction,根据标准ML(修订版)的定义: 其思想是,对非扩展表达式的动态求值既不会生成异常,也不会扩展内存域,而对扩展表达式的求值可能会产生异常 [§4.7,第19页;重点] 我在网上找到了很多关于ref-cell部分的信息,但是几乎没有关于exception部分的信息。(一些消息来源指出,多态绑定仍然可能引发Bind,这种不一致性可能会产生类型理论和/或实现后果,但我不确定这是否相关。) 我已经能够提出一个与异常相关的不健全,如果我没有弄错的话,它只能被值限制所阻止;但这种不健全并不取决于提出一个例外:

根据标准ML(修订版)的定义:

其思想是,对非扩展表达式的动态求值既不会生成异常,也不会扩展内存域,而对扩展表达式的求值可能会产生异常

[§4.7,第19页;重点]

我在网上找到了很多关于ref-cell部分的信息,但是几乎没有关于exception部分的信息。(一些消息来源指出,多态绑定仍然可能引发
Bind
,这种不一致性可能会产生类型理论和/或实现后果,但我不确定这是否相关。)

我已经能够提出一个与异常相关的不健全,如果我没有弄错的话,它只能被值限制所阻止;但这种不健全并不取决于提出一个例外:

local
  val (wrapAnyValueInExn, unwrapExnToAnyType) =
    let exception EXN of 'a
    in  (EXN, fn EXN value => value)
    end
in
  val castAnyValueToAnyType = fn value => unwrapExnToAnyType (wrapAnyValueInExn value)
end
那么,有谁能告诉我这个定义是什么意思,为什么它会提到例外


(有没有可能“生成异常”意味着生成异常名称,而不是生成异常包?

我不是类型理论家或形式语义学家,但我想我从操作的角度理解了该定义试图获得的内容

ML异常是生成的,这意味着,每当流的控制两次到达相同的异常声明时,就会创建两个不同的异常。这些对象不仅在内存中是不同的,而且在很大程度上也是不相等的:我们可以通过对异常构造函数进行模式匹配来区分这些对象

[顺便提一下,这显示了ML异常和大多数其他语言中的异常之间的重要区别。在ML中,可以在运行时创建新的异常类。]

另一方面,如果您的程序两次构建相同的整数列表,那么内存中可能有两个不同的对象,但您的程序无法区分它们。它们在很大程度上是相等的


作为生成异常为什么有用的一个例子,考虑MLTON的示例实现A:

如果ML没有值限制,该代码将导致一个巨大的类型安全孔:

val { inject = inj1, project = proj1 } = Univ.embed ()
val { inject = inj2, project = proj2 } = Univ.embed ()

(*  `inj1` and `proj1` share the same internal exception. This is
 *  why `proj1` can project values injected with `inj1`.
 *  
 *  `inj2` and `proj2` similarly share the same internal exception.
 *  But this exception is different from the one used by `inj1` and
 *  `proj1`.
 *  
 *  Furthermore, the value restriction makes all of these functions
 *  monomorphic.  However, at this point, we don't know yet what these
 *  monomorphic types might be.
 *)

val univ1 = inj1 "hello"
val univ2 = inj2 5

(*  Now we do know:
 *  
 *    inj1 : string -> Univ.univ
 *    proj1 : Univ.univ -> string option
 *    inj2 : int -> Univ.univ
 *    proj2 : Univ.univ -> int option
 *)

val NONE = proj1 univ2
val NONE = proj2 univ1

(*  Which confirms that exceptions are generative.  *)

val SOME str = proj1 univ1
val SOME int = proj2 univ2

(*  Without the value restriction, `str` and `int` would both
 *  have type `'a`, which is obviously unsound.  Thanks to the
 *  value restriction, they have types `string` and `int`,
 *  respectively.
 *)
[Hat tip to的回答是,该定义确实指的是这一点,并引入了“生成性例外”一词。我对他的答案投了更高的票,但我将其单独发布,因为我觉得他的答案在某种程度上是从错误的方向来回答这个问题的:大部分答案都是对问题已经预设的事物的阐述。]


“生成异常”是否可能意味着生成异常名称,而不是生成异常数据包

是的,我想是的。尽管定义通常不单独使用“异常”一词,但其他来源通常将异常名称称为“异常”——包括在生成它们的特定上下文中。例如,来自:

在标准ML中,异常声明被称为生成的,因为每次对异常声明求值时,它都会生成一个新的异常

(如您所见,该页面始终将异常名称称为“异常”。)

同样,标准的ML Basis库也以这种方式使用“exception”。例如,第29页:

在一个极端情况下,程序员可以在任何地方使用标准异常
General.Fail
,让它携带一个描述特定故障的字符串。[…]例如,一种技术是在结构
Sample
中使用函数
sampleFn
引发异常
Fail“Sample.sampleFn”

如您所见,本段使用术语“异常”两次,一次是指异常名称,一次是指异常值,这取决于上下文以明确含义


因此,定义中使用短语“生成异常”来表示生成异常名称是非常合理的(尽管如此,这可能是一个小错误;该定义通常比这更精确、更正式,并且通常表示它打算何时依赖上下文来消歧)。

嗨,感谢您的回复。似乎这个答案只是对我上一段中的问题回答“是”的一个漫长的过程?(因为除非我真的遗漏了什么,否则你使用的是术语“异常”,或者在一个地方使用“异常类”,来表示定义中所指的“异常名称”。)继续,进行更改。
val { inject = inj1, project = proj1 } = Univ.embed ()
val { inject = inj2, project = proj2 } = Univ.embed ()

(*  `inj1` and `proj1` share the same internal exception. This is
 *  why `proj1` can project values injected with `inj1`.
 *  
 *  `inj2` and `proj2` similarly share the same internal exception.
 *  But this exception is different from the one used by `inj1` and
 *  `proj1`.
 *  
 *  Furthermore, the value restriction makes all of these functions
 *  monomorphic.  However, at this point, we don't know yet what these
 *  monomorphic types might be.
 *)

val univ1 = inj1 "hello"
val univ2 = inj2 5

(*  Now we do know:
 *  
 *    inj1 : string -> Univ.univ
 *    proj1 : Univ.univ -> string option
 *    inj2 : int -> Univ.univ
 *    proj2 : Univ.univ -> int option
 *)

val NONE = proj1 univ2
val NONE = proj2 univ1

(*  Which confirms that exceptions are generative.  *)

val SOME str = proj1 univ1
val SOME int = proj2 univ2

(*  Without the value restriction, `str` and `int` would both
 *  have type `'a`, which is obviously unsound.  Thanks to the
 *  value restriction, they have types `string` and `int`,
 *  respectively.
 *)