我正在考虑如何使自己摆脱不确定性,而我的一个想法是列举所有可能的偏见来源。至少我会知道要当心。我发现了三个:
我听说过其他获得逻辑矛盾的方法,例如通过using negative types,但是我不确定这种情况是否适用于Haskell。那里有许多逻辑悖论,其中有些can be encoded in Haskell,但是否真的有任何逻辑悖论都需要使用递归,并因此在上面的第2点中得到了涵盖?
例如,如果已证明无递归的Haskell表达式始终可以求正态,则我给出的三点将是完整列表。我模糊地记得在西蒙·佩顿·琼斯(Simon Peyton Jones)的一本书中看到过类似的证明,但这是30年前写的,所以即使我没记错,它过去也适用于Haskell原型,今天可能是错误的,看看我们有多少种语言扩展。可能其中一些启用了其他方法来取消定义程序?
然后,如果检测到不能是部分的表达式非常容易,为什么我们不这样做呢?生活会多么轻松!
答案 0 :(得分:4)
这是部分答案(双关语是故意的),在这里,我仅列出一些可以实现不终止的可能不明显的方法。
首先,我将确认负递归类型确实可以导致非终止。确实,众所周知,允许使用递归类型,例如
data R a = R (R a -> a)
允许一个人定义fix
,并从那里获得非终止。
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS -Wall #-}
data R a = R (R a -> a)
selfApply :: R a -> a
selfApply t@(R x) = x t
-- Church's fixed point combinator Y
-- fix f = (\x. f (x x))(\x. f (x x))
fix :: forall a. (a -> a) -> a
fix f = selfApply (R (\x -> f (selfApply x)))
诸如Coq或Agda之类的全部语言通过要求递归类型仅使用严格的正递归来禁止这种情况。
另一个不可终止的潜在来源是Haskell允许Type :: Type
。据我所知,这使得可以在Haskell中对System U进行编码,在此可以使用吉拉德悖论引起逻辑上的不一致,从而构造类型Void
的术语。该术语(据我所知)不会终止。
不幸的是,吉拉德的悖论很难完全描述,我还没有完全研究它。我只知道它与所谓的超级游戏有关,该游戏的第一步是选择一个 finite 游戏。有限游戏是指导致每局比赛经过有限的多次移动后终止的游戏。此后的下一个动作将对应于在第一步中根据选定的有限游戏进行的比赛。这是自相矛盾的事情:由于所选游戏必须是有限的,无论它是什么,整个超游戏比赛总是会在经过有限的移动后终止。这使超级游戏本身成为有限游戏,从而使“我选择超级游戏,我选择超级游戏……”的无穷动作顺序成为有效的游戏,进而证明了超级游戏不是有限的。
显然,此参数可以在足够丰富的纯类型系统(如System U)中进行编码,并且Type :: Type
允许嵌入相同的参数。