虚无和荒谬的工作如何

时间:2018-05-14 19:02:37

标签: purescript

Void州的源代码:

newtype Void = Void Void

instance showVoid :: Show Void where
    show = absurd

absurd :: forall a. Void -> a
absurd a = spin a
    where
    spin (Void b) = spin b

似乎Void是无限递归类型,而absurd是无限递归函数。我尝试在REPL中运行show ((unsafeCoerce "lol") :: Void),它立即进入无限循环。

这里困扰我的是absurd :: forall a. Void -> a的类型签名。签名如何有效?编译器是否识别无限递归函数并允许它们具有任何返回类型,知道如果调用它们将永远不会实际终止?不仅absurd = unsafeCoerce具有相同的效果吗?

2 个答案:

答案 0 :(得分:5)

不,编译器无法识别无限循环函数。实际上已知这是不可能的 - 见Halting Problem

签名有效,因为函数体中没有任何内容可以确定(或有什么影响)返回类型应该是什么。因此,返回类型可以是任何东西。就这么简单。

Void的要点是,它是一种根本不具备任何价值的类型。就像一个空集。在这种情况下,通过使Void的每个值包含另一个值Void的聪明技巧来实现该属性,从而使得无法构造Void的值。这意味着,出于所有实际目的,类型Void不能具有任何值。

相应的函数absurd是一个永远不能被调用的函数。该属性遵循以Void为参数的函数。由于不存在类型Void的值,因此无法为此类函数提供参数,因此无法调用它。这种功能在一些非常高级的边缘情况下很有用,但大多数情况下它是理论上的好奇心。

答案 1 :(得分:4)

absurd的实现并不重要,因为不可能有Void的值 - 没有办法构建它。这也是为什么拥有这样一个功能是安全的 - 它不是无中生有的东西,它永远不会发生,所以它只用于类型检查器的证据。所以,unsafeCoerce也可以安全使用。

但是,是的,无限递归函数可以被输入为具有任何返回类型并且将进行类型检查 - 它不是在类型检查器中编码的特定特征,它只是从我们拥有的其他规则中脱离出来。查看它的一种方法是,由于函数是无限递归的,因此没有证据表明你将返回类型表示为无效。