如何用C ++ 11或Go等语言实现类型推断?

时间:2016-10-25 21:15:05

标签: algorithm compiler-construction type-inference

我在这里看到了this的问题,但它并没有特别详细地回答我的想法。 如果像Go或C ++ 11这样的语言不使用像Damas-Milner这样的推理算法,他们到底做了什么?我不认为它就像在右手边拿这个类型一样简单,因为如果你有类似的东西会怎么样:

5 + 3.4

编译器如何破译那是什么类型的?有没有算法不像

那么简单
if left is integer and right is float:
    return float;
if left is float and right is integer:
    return float;
etc... for every possible pattern

如果你能用简单的术语解释那些很棒的东西。我没有非常详细地研究编译器构造或任何理论主题,我也不是真正讲功能语言或复杂的数学符号。

1 个答案:

答案 0 :(得分:4)

  

我认为这不像在右侧采用类型那么简单

对于auto var = some_expression;形式的基本类型推断,就是这么简单。每个类型很好的表达式只有一种类型,该类型将是var的类型。不会从表达式的类型到另一种类型的隐式转换(如果您为var提供了显式类型,则可能存在。)

  

如果你有类似的东西怎么办?

5 + 3.4

问题“5 + 3.4的类型是什么?”并非特定于类型推断,C ++编译器总是必须回答这个问题 - 甚至在引入类型推断之前。

让我们退后一步,看看C ++编译器如何检查语句some_type var = some_expression;

首先,它确定some_expression的类型。因此,在代码中,您可以想象Type exp_type = type_of(exp);之类的内容。现在,它会检查exp_type是否等于some_type,还是存在从exp_typesome_type的隐式转换。如果是这样,那么该语句的类型很好,并且var被引入到具有类型some_type的环境中。否则就不是。

现在,当我们引入类型推断并编写auto var = some_expression;时,方程式会发生变化:我们仍然会Type exp_type = type_of(exp);,但不是将其与其他类型进行比较或应用任何隐式转换,而是简单地将exp_type设置为var的类型。

现在让我们回到5 + 3.4。它的类型是什么以及编译器如何确定它?在C ++中,它的类型是double。确定算术表达式类型的确切规则列在C ++标准中(查找“通常的算术转换”),但基本归结为:在两个操作数类型中,选择一个可以代表更大范围的操作数类型值。如果类型小于int,请将两个操作数转换为int。否则将两个操作数转换为您选择的类型。

在代码中,您可以通过为每个数字类型分配转换排名然后执行以下操作来实现此目的:

Type type_of_binary_arithmetic_expression(Type lhs_type, Type rhs_type) {
    int lhs_rank = conversion_rank(lhs_type);
    int rhs_rank = conversion_rank(rhs_type);
    if(lhs_rank < INT_RANK && rhs_rank < INT_RANK) return INT_TYPE;
    else if(lhs_rank < rhs_rank) return rhs_type;
    else return lhs_type;
}

据推测,Go的规则有所不同,但适用相同的原则。