【问题标题】:On context for resolving typing ambiguity in Standard ML关于在标准 ML 中解决类型歧义的上下文
【发布时间】:2015-03-18 03:19:28
【问题描述】:

我正在阅读 Robert Harper 的 Programming in Standard ML(11.02.11 的 1.2 版)。

关于解决类型推断的歧义。罗伯特哈珀说:

重要的问题是在情况被认为模棱两可之前考虑了多少上下文?经验法则是上下文被认为是最近的封闭函数声明。

因此,以下代码将被拒绝:

let
    val double = fn x => x + x
in
    (double 3.0, double 4.0)
end

我认为拒绝的原因是编译器无法确定doubleint->int还是real->real。代码 sn-p 没有提供足够的上下文来解决歧义。一些编译器默认将其设置为int->int,这使得代码 sn-p 类型错误。

我的问题是:

  1. “最近的封闭函数声明”是什么意思?

  2. 如何让编译器通过“最近的封闭函数声明”推断出函数double的类型是real -> real而不明确指定类型?

【问题讨论】:

    标签: types sml type-inference ml


    【解决方案1】:

    我认为拒绝的原因是编译器无法确定doubleint->int 还是real->real。代码 sn-p 没有提供足够的上下文来解决歧义。一些编译器默认将其设置为int->int,这使得代码 sn-p 类型错误。

    这大部分是正确的,除了代码 sn-p 实际上确实提供了足够的上下文来解决歧义(至少可以排除int -> int);只是一些编译器在决定+ 的类型时只会考虑最小的封闭声明(在这种情况下为val double = fn x => x + x),甚至更少。这实际上就是这篇文章的内容——编译器必须决定要考虑多少上下文,有些编译器考虑的比其他编译器少。

    + 默认为int * int -> int,在没有足够的上下文以不同方式解决歧义的情况下,实际上是由定义的附录 E 规定的。

    1. “最近的封闭函数声明”是什么意思?

    表示包含重载运算符或常量的最小函数声明。在这种情况下,重载的运算符是+,它最近的封闭函数声明是val double = fn x => x + x

    1. 如何让编译器在不明确指定类型的情况下,通过“最近的封闭函数声明”推断出函数double的类型是real -> real

    如果您只是不想指定整个real -> real,那么您可以这样写:

    val double = fn x => x + (x : real)
    

    如果您的意思是根本不需要任何显式类型注释,那么我认为唯一的选择就是写一些有点骇人听闻的东西,例如:

    val double = fn x => x + x + 0.0
    

    或者你可以选择:

    val double = fn x => 2.0 * x
    

    【讨论】:

    • 谢谢。但是在这种情况下,“最近的封闭函数声明”是否意味着整个 val double = fn x => x + x 函数声明?如果它只表示+ 默认为int->int,那么val double: real->real = fn x => x + x 不会是错误类型的吗?
    • @Ben:“重载的运算符或常量(在本例中为 +)”我的意思是在本例中 + 是重载的运算符或常量,不是 在这种情况下,+ 是最近的封闭函数声明。我现在改写了一些措辞以消除这种歧义。
    猜你喜欢
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    相关资源
    最近更新 更多