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:抱歉我的英语不好;这不是我的母语。答案 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
的内容,则可以立即断定a
和b
必须是整数 - 但在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)