编译器如何确定sml

时间:2015-12-13 00:05:40

标签: 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 => fn a => fn b => a

的类型为:

'a -> 'b -> 'c -> 'b

因为'if(f a)'我们可以得出'a必须是一个接受类型'b的函数并输出一个布尔值,否则它将不起作用。

('b->bool) -> 'b -> 'c -> 'b

这样做'a是开始:

('a->bool) -> 'a -> 'b -> 'a

是我从中获得的最终答案。但是,当我在命令提示符下输入它时,我得到以下类型:

(bool->bool) -> bool -> bool -> bool
我错过了什么?在什么时候'a和'b(来自我的最终类型评估)专注于bool?

1 个答案:

答案 0 :(得分:5)

  

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

标准ML使用Damas-Hindley-Milner type inference,但有几种算法可用于解析most general type,特别是算法W.类型推理规则在例如

  

' a和&b; b专门用于bool?

' ' b 专门针对bool的确切位置取决于所使用的算法。我将跳过并跳过表达式被赋予类型的一些步骤,并且这些类型是统一的。

当它显示if (f a) then a else raise Break时,则

  • a t 1
  • f t 1 →bool
  • if ... t 1

同样地,当它说if not (f a) then a else b时,我们还有那个

  • b t 1

最后,f (raise Break) handle Break => if ... then a else ...为我们提供了

  • f (raise Break) bool
  • t 1 = bool ,因为f (raise Break)if ... then a else ...必须具有相同的类型。

您遗失的部分可能意识到,对于x handle ... => yxy必须具有相同的类型。否则,您将拥有一个根据是否抛出异常而更改类型的表达式。在编译期间解析类型并在运行时抛出异常时,这是不可能的。这是相关的一个实际例子是否定测试,其中handle ...左侧的类型被强制为右侧的类型:

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