Haskell给f x = f x
类型t1 -> t
,但有人可以解释原因吗?
并且,任何其他非等效函数是否可能具有相同的类型?
答案 0 :(得分:16)
好的,从功能定义f x = f x
开始,让我们一步一步看看我们可以推断出f
的类型。
从完全未指定的类型变量a
开始。我们能推断出更多吗?是的,我们观察到f
是一个带有一个参数的函数,因此我们可以将a
更改为两个未知类型变量之间的函数,我们将其称为b -> c
。 b
所代表的类型是参数x
的类型,c
所代表的类型必须是定义右侧的类型。
我们可以弄清楚右侧的哪些方面?好吧,我们有f
,它是我们定义的函数的递归引用,因此它的类型仍然是b -> c
,其中两个类型变量与{{1}的定义相同}。我们还有f
,它是x
定义中的变量,其类型为f
。将b
应用于f
类型检查,因为它们共享相同的未知类型x
,结果为b
。
此时所有东西都在一起,没有其他限制,我们可以使类型变量“正式”,从而产生最终类型c
,其中两个变量都是Haskell中通常的,隐式普遍量化的类型变量
换句话说,b -> c
是一个函数,它接受任何类型的参数并返回任何类型的值。它如何返回任何可能的类型?它不能,我们可以观察到它的评估只会产生无限的递归。
出于同样的原因,任何具有相同类型的函数在评估时永远不会返回“等效”。
更直接的版本是完全删除参数:
f
......这也是普遍量化的,代表任何类型的价值。这几乎相当于foo :: a
foo = foo
。
答案 1 :(得分:7)
f x = undefined
具有(alpha)等效类型f :: t -> a
。
如果你很好奇,Haskell的类型系统来自Hindley–Milner。非正式地,类型检查器以一切最宽松的类型开始,并统一各种约束,直到剩下的是一致的(或不是)。在这种情况下,最常见的类型是f :: t1 -> t
,并且没有其他约束。
与
比较f x = f (f x)
由于统一了LHS上f :: t -> t
的参数类型和RHS上外部f
的参数,推断出类型f
。