【发布时间】:2018-08-15 01:27:27
【问题描述】:
定义此数据类型:
data NaturalNumber = Zero | S NaturalNumber
deriving (Show)
在 Haskell(使用 GHC 编译)中,此代码将在没有警告或错误的情况下运行:
infinity = S infinity
inf1 = S inf2
inf2 = S inf1
所以递归和相互递归的无限深值都通过了类型检查。
但是,下面的代码给出了错误:
j = S 'h'
错误状态为Couldn't match expected type ‘NaturalNumber’ with actual type 'Char'。即使我设置了(相同的)错误仍然存在
j = S (S (S (S ... (S 'h')...)))
有一百个左右嵌套的S's。
Haskell 如何判断 infinity 是 NaturalNumber 的有效成员,但 j 不是?
有趣的是,它还允许:
bottom = bottom
k = S bottom
Haskell 是否只是试图证明程序的不正确性,如果它没有这样做,那么就允许它?还是 Haskell 的类型系统不是图灵完备的,所以如果它允许程序,那么程序可证明(在类型级别)是正确的?
(如果类型系统(在 Haskell 的形式语义中,而不仅仅是类型检查器)是图灵完备的,那么它将无法意识到某些正确类型的程序是正确的,或者某些错误类型的程序是不正确的,由于停止问题的不可判定性。)
【问题讨论】:
-
您可能有兴趣阅读有关 Hindley-Milner 类型推断的信息。 GHC 有一种双向类型检查的形式。查看
infinity时,Haskell 将尝试合成infinity :: NaturalNumber(因为它是使用S :: NaturalNumber -> NaturalNumber构造的)然后检查infinity :: NaturalNumber(因为infinity是给S的参数)。 -
好的——所以本质上它会猜测类型(以某种智能方式),然后尝试查看类型是否匹配?那么是否有任何保证(类型检查器的)终止并得到正确的结果?
标签: haskell types infinite typechecking type-systems