Types 编译器如何确定sml中的类型

Types 编译器如何确定sml中的类型,types,sml,smlnj,Types,Sml,Smlnj,我得到了以下代码,并被要求确定类型 exception Break; fn f => fn a => fn b => (f(raise Break) handle Break => if (f a) then a else raise Break) handle Break => if not(f a) then a else b; 我知道该函数在所有情况下都接受f、a和b并输出a,因此它必须等价于: fn f =>

我得到了以下代码,并被要求确定类型

exception Break;
fn f => fn a => fn b =>
    (f(raise Break)
       handle Break => if (f a) then a else raise Break)
          handle Break => if not(f a) then a else b;
我知道该函数在所有情况下都接受f、a和b并输出a,因此它必须等价于:

fn f => fn a => fn b => a
其类型为:

'a -> 'b -> 'c -> 'b
因为‘if(fa)’我们可以推导出‘a必须是一个接受‘b’类型并输出布尔值的函数,否则它将无法工作

('b->bool) -> 'b -> 'c -> 'b
“重做”是一个开始:

('a->bool) -> 'a -> 'b -> 'a
这就是我最后的答案。但是,当我在命令提示符下键入时,会得到以下类型:

(bool->bool) -> bool -> bool -> bool
我错过了什么?“a”和“b”(从我最后的类型评估中)在什么时候专门化为bool

编译器如何确定sml中的类型

标准ML使用,但有几种算法用于解析,尤其是算法W。类型推断规则在

  • [PS],它实际上主要提供了一种更有效的替代算法G,但导言非常容易阅读,并给出了推断小表达式类型的完整示例
  • ,它引入了刚好足够的类型理论来解释StackOverflow问题
“a”和“b”在什么时候专精于布尔

“a”和“b”专门化为布尔的确切点取决于所使用的算法。我将跳过一些步骤,其中表达式是给定类型的,并且这些类型是统一的

当它说
如果(fa)那么一个else提升中断
,那么

  • a
    :t1
  • f
    :t1→ 布尔
  • 如果…
    :t1
同样地,当它说
如果不是(fa),那么a,else,b
时,我们还有这个

  • b
    :t1
最后,如果。。。然后另一个…告诉我们

  • f(上升制动)
    :bool
  • t1=bool,因为
    f(上升-断开)
    如果。。。那么一个else…
    必须具有相同的类型
您缺少的部分可能是意识到对于
x句柄…=>y
x
y
必须具有相同的类型。否则,您将拥有一个根据是否引发异常而改变类型的表达式。如果在编译期间解析类型,并且在运行时抛出异常,则这是不可能的。与此相关的一个实际示例是阴性测试,其中
手柄左侧的类型强制为右侧的类型:

val factorial_robust_test = (factorial -1; false)
                            handle Domain => true
                                 | Overflow => false
                                 | _ => false