向C ++程序员解释ML类型推断

时间:2010-04-20 19:22:27

标签: c++ functional-programming templates type-inference ml

ML如何在以下函数定义中执行类型推断:

let add a b = a + b

是否像C ++模板一样,在模板实例化之前不执行类型检查,如果类型支持必要的操作,函数可以工作,否则会抛出编译错误?

即。例如,以下功能模板

template <typename NumType>
NumType add(NumType a, NumType b) {
  return a + b;
}

适用于

add<int>(23, 11);

但不适用于

add<ostream>(cout, fout);

我猜的是正确的还是ML类推断的工作方式不同?

PS:抱歉我的英语不好;这不是我的母语。

4 个答案:

答案 0 :(得分:5)

我建议你看一下这篇文章:What is Hindley-Milner? (and why is it cool)

这是他们用来解释类型推断的最简单的例子(它不是ML,但想法是一样的):

def foo(s: String) = s.length
// note: no explicit types
def bar(x, y) = foo(x) + y

只要查看bar的定义,我们就可以很容易地看到它的类型必须是(String,Int)=&gt; Int。简而言之,这就是类型推断。阅读整篇文章以获取更多信息和示例。

我不是C ++专家,但我认为模板是更接近于通用性/参数性的其他东西,这是不同的东西。

答案 1 :(得分:5)

我认为尝试将ML类型推理与C ++中的几乎任何事物联系起来更容易导致混淆而不是理解。 C ++根本没有任何类似于类型推断的东西。

C ++中唯一没有明确键入的部分是模板,但(大多数情况下)它们支持泛型编程。您给出的C ++函数模板可能同样适用于无限类型集 - 例如,您使用的代码NumType作为模板参数,但可以使用字符串。一个程序可以实例化你的add以在一个地方添加两个字符串,在另一个地方添加两个数字。

ML类型推断不适用于通用编程。在C或C ++中,您显式定义了参数的类型,然后编译器会检查该类型是否允许您尝试对该参数执行的所有操作。 ML反驳说:它会查看您使用参数执行的操作,并确定具有类型的内容,以便您能够执行这些操作。如果你试图做一些相互矛盾的事情,它会告诉你没有能够满足约束的类型。

这在C或C ++中几乎是不可能的,主要是因为允许的所有隐式类型转换。例如,如果我在ML中有类似a + b的内容,则可以立即断定ab必须是整数 - 但在C或C ++中,它们几乎可以是任意组合整数或指针或浮点类型(具有它们不能两者都是指针的约束)或使用重载operator+的定义类型(例如,std::string)。在ML中,在最坏的情况下找到类型可以是指数,但几乎总是非常快。在C ++中,我估计它更频繁地呈指数形式,并且在很多情况下可能会受到限制,因此给定的函数可能具有许多不同的签名。

答案 2 :(得分:4)

ML使用Hindley-Milner type inference。在这个简单的例子中,它所要做的只是查看函数体,并看到它使用带有参数的+并返回它。因此,它可以推断出参数必须是+接受的参数类型(即int),并且函数返回+返回的类型(也是int)。因此,add的推断类型为int -> int -> int

请注意,在SML(但不是CAML)中,+也是为除int之外的其他类型定义的,但是当有多种可能性时它仍会推断int(即你定义的add函数不能用于添加两个浮点数。)

答案 3 :(得分:0)

F#和ML在类型推断方面有些相似,所以你可能会找到

Overview of type inference in F#

有帮助的。