我如何分配一个具有自由类型变量的表达式,就像我将其他函数 f 分配为 val x = f :?
how do I assign an expression with free type variables, like I assign other functions f as val x = f :?
如何为表达式分配自由类型变量,就像我将其他函数 f 分配为 val x = f : ??
我有
fun curry f x y = f (x,y);
val dummy = fn (x,y) => {a=x,b=y} (* or anything with free type *)
val dummCd = fn x=> fn y=> {a=x,b=y}
我认为 'curry dummy' 会像 'dummCd' 一样工作,但是,
dummCd
val it = fn: 'a -> 'b -> {a: 'a, b: 'b}
和
curry dummy:
stdIn:13.1-13.8 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val it = fn : ?.X1 -> ?.X2 -> {a:?.X1, b:?.X2}
所以这在分配时变得无用。
我可以这样做:
fun x a b =curry dummy a b ;
但这有点笨拙。当我把我在这里做的事情放到一个函数中时
val a = fn tr => (fn a=> fn b=> tr a b)
val x = a (curry dummy)
val x = fn : ?.X1 -> ?.X2 -> {a:?.X1, b:?.X2}
我遇到了同样的问题。
如何在不使用额外的 a 和 b 的情况下分配 'curry dummy' ?我是说喜欢
val x = a ( curry dummy )
其中 a 可能是一个函数,而 x 的行为类似于 dummCd
感谢提示
遗憾的是,你不能如愿以偿。
在 Standard ML '97 中,如果绑定的右侧是 "non-expansive" 表达式,则值声明只能绑定类型变量,这意味着它符合表达式的非常严格的子集无法生成任何新的引用单元格或异常名称的语法。由于这是一个 syntactic 检查,它根本没有考虑 curry
的定义; 你 知道 curry
不会创建任何引用单元或异常名称(因此 val dummCd = curry dummy
是安全的),但所有编译器此时都看到是 curry dummy
调用了一个 可以 做那些事情的函数。
因此,如果您希望 dummCd
以任意类型调用(意思是,您希望它具有非平凡类型方案∀αβ.α→β→{a:α,b:β}绑定类型变量),那么您需要使用例如声明它val dummCd = fn ...
或 fun dummCd ...
;你不能只在右侧写 val dummCd = ...
和任何你想要的东西。
Standard ML '90 在这方面有点宽松——它将有关 curry
行为的相关信息编码到类型系统中(通过将类型变量标记为 "imperative",例如'_a
而不是 'a
,如果它涉及任何引用单元格或异常名称的类型),并使用该类型信息来决定是否应允许 val dummCd = curry dummy
绑定其类型变量— 但该系统被认为过于混乱和复杂,特别是因为它强制将实现细节纳入签名,因此它在 Standard ML '97 中被废弃并替换为当前的仅语法系统,其中假定所有类型变量都是命令式的。
如何为表达式分配自由类型变量,就像我将其他函数 f 分配为 val x = f : ??
我有
fun curry f x y = f (x,y);
val dummy = fn (x,y) => {a=x,b=y} (* or anything with free type *)
val dummCd = fn x=> fn y=> {a=x,b=y}
我认为 'curry dummy' 会像 'dummCd' 一样工作,但是,
dummCd
val it = fn: 'a -> 'b -> {a: 'a, b: 'b}
和
curry dummy:
stdIn:13.1-13.8 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val it = fn : ?.X1 -> ?.X2 -> {a:?.X1, b:?.X2}
所以这在分配时变得无用。 我可以这样做:
fun x a b =curry dummy a b ;
但这有点笨拙。当我把我在这里做的事情放到一个函数中时
val a = fn tr => (fn a=> fn b=> tr a b)
val x = a (curry dummy)
val x = fn : ?.X1 -> ?.X2 -> {a:?.X1, b:?.X2}
我遇到了同样的问题。 如何在不使用额外的 a 和 b 的情况下分配 'curry dummy' ?我是说喜欢
val x = a ( curry dummy )
其中 a 可能是一个函数,而 x 的行为类似于 dummCd
感谢提示
遗憾的是,你不能如愿以偿。
在 Standard ML '97 中,如果绑定的右侧是 "non-expansive" 表达式,则值声明只能绑定类型变量,这意味着它符合表达式的非常严格的子集无法生成任何新的引用单元格或异常名称的语法。由于这是一个 syntactic 检查,它根本没有考虑 curry
的定义; 你 知道 curry
不会创建任何引用单元或异常名称(因此 val dummCd = curry dummy
是安全的),但所有编译器此时都看到是 curry dummy
调用了一个 可以 做那些事情的函数。
因此,如果您希望 dummCd
以任意类型调用(意思是,您希望它具有非平凡类型方案∀αβ.α→β→{a:α,b:β}绑定类型变量),那么您需要使用例如声明它val dummCd = fn ...
或 fun dummCd ...
;你不能只在右侧写 val dummCd = ...
和任何你想要的东西。
Standard ML '90 在这方面有点宽松——它将有关 curry
行为的相关信息编码到类型系统中(通过将类型变量标记为 "imperative",例如'_a
而不是 'a
,如果它涉及任何引用单元格或异常名称的类型),并使用该类型信息来决定是否应允许 val dummCd = curry dummy
绑定其类型变量— 但该系统被认为过于混乱和复杂,特别是因为它强制将实现细节纳入签名,因此它在 Standard ML '97 中被废弃并替换为当前的仅语法系统,其中假定所有类型变量都是命令式的。