2016-02-03 122 views
2

我试图围绕OCaml的类型推断符号包裹我的头。OCaml中的类型推理

例如:

# let f x = x [];; 
val f : ('a list -> 'b) -> 'b = <fun> 

对我来说很有意义。 val f需要一个函数x,它接受一个'a类型的列表并返回'b类型的东西。然后f返回一个'b类型,因为它只是调用x。

但是,一旦我们得到更多的论据,我会变得更加困惑。

# let g a b c = a b c;; 
val g : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c = <fun> 

我可以假设如果函数有参数,那么类型推断的第一个参数将始终是参数?如果我称之为b c,是((a b)c)还是(a(b c))的顺序?

# let rec h m n ls = match ls with 
    | [] -> n 
    | x::t -> h m (m n x) t;; 
val h : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun> 

作为该一个我很困惑,如何( '一个 - >' B - > '一) - >' 一个推导。我可以看到'b列表对应于ls变量,最后'a对应于终端符号n的类型。

回答

3

我可以假设如果函数有参数,那么类型推断的第一个参数将始终是参数?

是的,函数类型的第一个参数是它的第一个参数的类型。

如果我打电话给bc,是((a b)c)还是(a(b c))?

的顺序是((a b) c)(你可以认为这个简单的方法)

至于这一次我很困惑,如何( 'A - >' B - >“一) - > 'a得到了。我可以看到'b列表对应于ls变量,最后'a对应于终端符号n的类型。

你说得对。 ls有型号'b listn有型号'a

让我们想想的m类型:

  1. 你知道n已键入'a,这样你就可以得到(m n x)也 已键入'a
  2. 你知道ls的类型为'b list,这样你就可以得到x有 类型'b
  3. m需要两个参数'a和类型'b,并生成'a类型的结果。因此,m具有类型'a -> 'b -> 'a

因此,整个函数的类型是('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

+0

太谢谢你了!这为我清理了很多。如果您不介意回答,我只需再做一次后续处理:如果我们不知道类型推断,只能从方程式中找出答案,该怎么办?你如何知道m的第二个arg a.k.a. x是'b'类型的,与'a'不一样? –

+0

@ChangLiu对于像你这样简单的功能,你可以通过统一来推断。以一种非常幼稚的方式,分配类型为''''''''的''''''''''''''''''''''''''''''类型''''''''''''''''''' ,你可以为这些变量定义方程,并求解方程以得出最基本的类型(''''''''''''''''''''')。您可以搜索“算法W”以获取更多关于类型推断的信息。或者,你可以在OCaml中编程更多,这样你就可以更快地进行推理:) – objmagic