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