Answers:
有关Go的类型推断,请参见此StackOverflow答案。我不熟悉Go自己,但基于此答案,这似乎是一种单向的“类型推导”(借用一些C ++术语)。这意味着如果您具有:
x := y + z
然后x
通过找出的类型来推导的类型y + z
,这对于编译器而言是一件相对琐碎的事情。要做到这一点,其种类y
和z
需要了解的先验:这可以通过类型注释完成或分配给他们的文字推断。
相反,大多数功能语言具有类型推断功能,该类型推断功能使用模块(或函数,如果推断算法是局部的)中的所有可能信息来得出变量的类型。复杂的推理算法(例如Hindley-Milner)通常在幕后涉及某种形式的类型统一(有点像求解方程式)。例如,在Haskell中,如果您编写:
let x = y + z
然后哈斯克尔可以推断不仅种类x
,而且y
与z
基于您正在执行的加入对他们其实根本。在这种情况下:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(a
这里的小写字母表示多态类型,在其他语言(如C ++)中通常称为“泛型”。该Num a =>
部分是约束,表明类型a
支持具有某些加法概念。)
这是一个更有趣的示例:允许定义任何递归函数的定点组合器:
let fix f = f (fix f)
请注意,我们在哪里都没有指定的类型f
,也没有指定的类型fix
,但是Haskell编译器可以自动找出:
f :: t -> t
fix :: (t -> t) -> t
这样说:
f
必须是从任意类型t
到相同类型的函数t
。fix
是接收类型参数t -> t
并返回类型结果的函数t
。Go中的类型推断非常有限且非常简单。它仅在一种语言构造(变量声明)中起作用,并且仅采用右侧的类型并将其用作左侧变量的类型。
Haskell中的类型推断可在任何地方使用,它可用于推断整个程序的类型。它基于统一,这意味着(从概念上来说)所有类型都是“一次”推断的,并且它们都可以相互影响:在Go中,类型信息只能从变量声明的右侧流向左侧,另一方面,永远不要在另一个方向,永远不要在变量声明之外;在Haskell中,类型信息在整个程序中向各个方向自由流动。
但是,Haskell的类型系统是如此强大,以至于类型推断实际上无法推断出类型(或更准确地说:必须施加限制,以便始终可以推断出类型)。Go的类型系统非常简单(没有子类型,没有参数多态性),其推理如此有限,以至于它总是成功。
x
,y
,z
都是一样的Num
埃里克类型,但他们仍然可以Integer
S,Double
S,Ratio Integer
S ^ ... Haskell是愿意做数字类型之间任意选择,但不支持其他类型类。