值多态性和"generating an exception"
Value polymorphism and "generating an exception"
根据 标准 ML 的定义(修订版):
The idea is that dynamic evaluation of a non-expansive expression will neither generate an exception nor extend the domain of the memory, while the evaluation of an expansive expression might.
[§4.7,第 19 页;强调我的]
我在网上找到了很多关于 ref-cell 部分的信息,但几乎 none 关于异常部分的信息。 (一些消息来源指出,多态绑定仍然有可能引发 Bind
,并且这种不一致可能会产生类型理论上的 and/or 实现后果,但我不确定这是否相关。)
我已经能够想出一个与异常相关的不合理性,如果我没记错的话,它只能通过值限制来防止;但这种不健全并不取决于提出一个例外:
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
那么,谁能告诉我 Definition 的含义,以及为什么它会提到例外情况?
(有没有可能"generate an exception"是生成异常name,而不是生成异常packet?)
我不是类型理论家或形式语义学家,但我想我从操作的角度理解该定义试图达到的目的。
ML 异常生成意味着,每当流控制两次到达相同的异常声明时,将创建两个不同的异常。不仅内存中存在这些不同的对象,而且这些对象在外延上也是不相等的:我们可以通过针对异常构造函数的模式匹配来区分这些对象。
[顺便说一句,这显示了 ML 异常和大多数其他语言中的异常之间的重要区别。在 ML 中,可以在运行时创建新异常 类。]
另一方面,如果您的程序两次构建相同的整数列表,您可能在内存中有两个不同的对象,但您的程序无法区分它们。它们在外延上是相等的。
作为生成异常为何有用的示例,请考虑 MLton 的示例实现 universal type:
signature UNIV =
sig
type univ
val embed : unit -> { inject : 'a -> univ
, project : univ -> 'a option
}
end
structure Univ :> UNIV =
struct
type univ = exn
fun 'a embed () =
let
exception E of 'a
in
{ inject = E
, project = fn (E x) => SOME x | _ => NONE
}
end
end
如果 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.
*)
[对 Eduardo León 的回答的提示,说明 定义 确实指的是这个,并引入了短语 "generative exceptions" .我赞成他的回答,但我将其单独发布,因为我觉得他的回答是从错误的方向来回答问题的,有点:大部分答案都是对问题已经预设的事物的阐述。]
Is it possible that "generate an exception" means generating an exception name, rather than generating an exception packet?
是的,我想是的。尽管 Definition 通常不单独使用 "exception" 这个词,但其他来源通常将异常名称简单地称为 "exceptions" — 包括在生成的特定上下文中他们。例如,来自 http://mlton.org/GenerativeException:
In Standard ML, exception declarations are said to be generative, because each time an exception declaration is evaluated, it yields a new exception.
(如您所见,该页面始终将异常名称称为 "exceptions"。)
Standard ML Basis Library,同样是这样使用"exception"。例如,从第 29 页开始:
At one extreme, a programmer could employ the standard exception General.Fail
everywhere, letting it carry a string describing the particular failure. […] For example, one technique is to have a function sampleFn
in a structure Sample
raise the exception Fail "Sample.sampleFn"
.
如您所见,本段使用术语 "exception" 两次,一次引用异常名称,一次引用异常值,依赖上下文使含义清晰。
所以定义用"generate an exception"这个短语来指代生成异常名是很合理的(尽管如此,这可能是一个小错误; Definition 通常比这个更精确和正式,并且通常表明它何时打算依赖上下文来消除歧义。
根据 标准 ML 的定义(修订版):
The idea is that dynamic evaluation of a non-expansive expression will neither generate an exception nor extend the domain of the memory, while the evaluation of an expansive expression might.
[§4.7,第 19 页;强调我的]
我在网上找到了很多关于 ref-cell 部分的信息,但几乎 none 关于异常部分的信息。 (一些消息来源指出,多态绑定仍然有可能引发 Bind
,并且这种不一致可能会产生类型理论上的 and/or 实现后果,但我不确定这是否相关。)
我已经能够想出一个与异常相关的不合理性,如果我没记错的话,它只能通过值限制来防止;但这种不健全并不取决于提出一个例外:
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
那么,谁能告诉我 Definition 的含义,以及为什么它会提到例外情况?
(有没有可能"generate an exception"是生成异常name,而不是生成异常packet?)
我不是类型理论家或形式语义学家,但我想我从操作的角度理解该定义试图达到的目的。
ML 异常生成意味着,每当流控制两次到达相同的异常声明时,将创建两个不同的异常。不仅内存中存在这些不同的对象,而且这些对象在外延上也是不相等的:我们可以通过针对异常构造函数的模式匹配来区分这些对象。
[顺便说一句,这显示了 ML 异常和大多数其他语言中的异常之间的重要区别。在 ML 中,可以在运行时创建新异常 类。]
另一方面,如果您的程序两次构建相同的整数列表,您可能在内存中有两个不同的对象,但您的程序无法区分它们。它们在外延上是相等的。
作为生成异常为何有用的示例,请考虑 MLton 的示例实现 universal type:
signature UNIV =
sig
type univ
val embed : unit -> { inject : 'a -> univ
, project : univ -> 'a option
}
end
structure Univ :> UNIV =
struct
type univ = exn
fun 'a embed () =
let
exception E of 'a
in
{ inject = E
, project = fn (E x) => SOME x | _ => NONE
}
end
end
如果 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.
*)
[对 Eduardo León 的回答的提示,说明 定义 确实指的是这个,并引入了短语 "generative exceptions" .我赞成他的回答,但我将其单独发布,因为我觉得他的回答是从错误的方向来回答问题的,有点:大部分答案都是对问题已经预设的事物的阐述。]
Is it possible that "generate an exception" means generating an exception name, rather than generating an exception packet?
是的,我想是的。尽管 Definition 通常不单独使用 "exception" 这个词,但其他来源通常将异常名称简单地称为 "exceptions" — 包括在生成的特定上下文中他们。例如,来自 http://mlton.org/GenerativeException:
In Standard ML, exception declarations are said to be generative, because each time an exception declaration is evaluated, it yields a new exception.
(如您所见,该页面始终将异常名称称为 "exceptions"。)
Standard ML Basis Library,同样是这样使用"exception"。例如,从第 29 页开始:
At one extreme, a programmer could employ the standard exception
General.Fail
everywhere, letting it carry a string describing the particular failure. […] For example, one technique is to have a functionsampleFn
in a structureSample
raise the exceptionFail "Sample.sampleFn"
.
如您所见,本段使用术语 "exception" 两次,一次引用异常名称,一次引用异常值,依赖上下文使含义清晰。
所以定义用"generate an exception"这个短语来指代生成异常名是很合理的(尽管如此,这可能是一个小错误; Definition 通常比这个更精确和正式,并且通常表明它何时打算依赖上下文来消除歧义。