相互递归的类型推断
我一直在思考类型推断如何在以下 OCaml 程序中工作:
let rec f x = (g x) + 5
and g x = f (x + 5);;
当然,该程序毫无用处(永远循环),但是类型呢? OCaml 说:
val f : int -> int = <fun>
val g : int -> int = <fun>
这正是我的直觉,但是类型推断算法如何知道这一点?
假设算法首先考虑“f”:它可以得到的唯一约束是“g”的返回类型必须是“int”,因此它自己的返回类型也是“int”。但它无法通过“f”的定义推断其参数的类型。
另一方面,如果它首先考虑“g”,它可以看到它自己的参数的类型必须是“int”。但如果之前没有考虑过“f”,它就无法知道“g”的返回类型也是“int”。
它背后有何魔力?
I've been thinking about how type inference works in the following OCaml program:
let rec f x = (g x) + 5
and g x = f (x + 5);;
Granted, the program is quite useless (looping forever), but what about the types?
OCaml says:
val f : int -> int = <fun>
val g : int -> int = <fun>
This would exactly be my intuition, but how does the type inference algorithm know this?
Say the algorithm considers "f" first: the only constraint it can get there is that the return type of "g" must be "int", and therefore its own return type is also "int". But it cannot infer the type of its argument by the definition of "f".
On the other hand, if it considers "g" first, it can see that the type of its own argument must be "int". But without having considered "f" before, it can't know that the return type of "g" is also "int".
What is the magic behind it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
它无法将其推断为具体类型,但可以推断出某些内容。即:
f
的参数类型必须与g
的参数类型相同。所以基本上在查看f
后,ocaml 知道以下有关类型的信息:在查看
g
后,它知道'a
必须是int
。要更深入地了解类型推断算法的工作原理,您可以阅读有关 Hindley-Milner 类型推断 或 这篇博文,看起来比维基百科的文章友好得多。
It can't infer it to a concrete type, but it can infer something. Namely: the argument type of
f
must be the same as the argument type ofg
. So basically after looking atf
, ocaml knows the following about the types:After looking at
g
it knows that'a
must beint
.For a more in-depth look on how the type inference algorithm works, you can read the Wikipedia article about Hindley-Milner type inference or this blog post, which seems to be much friendlier than the Wikipedia article.
这是我对所发生事情的心理模型,它可能与现实相符,也可能不相符。
好的,此时我们知道
f
是一个接受参数x
的函数。因此我们有:对于一些
'a
和'b
。下一步:好的,现在我们知道
g
是一个可以应用于x
的函数,因此我们将其添加到信息列表中。继续...
啊哈,
g
的返回类型必须是int
,所以现在我们已经解决了'c=int
。此时我们有:继续...
好吧,这里有一个不同的
x
,让我们假设原始代码有y
,以使事情更加明显。也就是说,让我们将代码重写为“Ok”,现在
我们的信息是:
因为
y
是g
的参数...我们继续:并且这从
y+5
告诉我们,y
的类型为int
,这解决了'a=int
问题。由于这是g
的返回值,我们已经知道它必须是int
,所以这就解决了'b=int
。一步完成了很多工作,如果代码是,那么第一行将显示
y
是一个int
,从而解决'a
,然后下一行会说r
的类型为'b
,最后一行是g
的返回,这解决了'b=int
。Here is my mental model of what goes on, which may or may not match reality.
Ok, at this point we know that
f
is a function that takes argumentx
. Thus we have:for some
'a
and'b
. Next:Ok, now we know
g
is a function that can be applied tox
, so we addto our list of information. Continuing...
Aha, the return type of
g
must beint
, so now we have solved'c=int
. At this point we have:Moving on...
Ok, there's a different
x
here, let's assume the original code hady
instead, to keep things more obvious. That is, let's rewrite the code asOk, so we are at
so now our info is:
since
y
is an argument tog
... and we keep going:and this tells us from
y+5
thaty
has typeint
, which solves'a=int
. And since this is the return value ofg
, which we already know must beint
, this solves'b=int
. That was a lot in one step, if the code werethen the first line would show
y
is anint
, thus solving for'a
, and then the next line would say thatr
has type'b
, and then the final line is the return ofg
, which solves'b=int
.