依赖类型通常被宣传为一种使您能够断言程序是否符合规范的方法。因此,例如,要求您编写对列表进行排序的代码 - 您可以通过编码" sort"的概念来证明代码是正确的。作为一种类型,并编写诸如List a -> SortedList a
之类的函数。但是,您如何证明规范SortedList
是正确的?事实并非如此,您的规范越复杂,您对该规范作为类型的编码就越不正确吗?
答案 0 :(得分:37)
这是How do you tell that your tests are correct?
的静态类型系统版本我可以诚实地给出的唯一答案是,是的,您的规范越复杂和笨拙,您犯错的可能性就越大。你可以在类型理论形式主义中写一些东西,就像你将程序的描述形式化为可执行函数一样。
希望你的规范简单而且小到足以通过检查来判断,而你的实现可能要大得多。一旦你有一些种子"它就会有所帮助。正式化的想法,你可以表明从这些想法得出的想法是正确的。从这个角度来看,您可以更容易地从更简单的部分机械地和可证地推导出您的规范的一部分,并最终从您的规范中推导出您的实现,您越有可能获得正确的实现。
但是不清楚如何将某些东西形式化,这可能会导致您在将您的想法转化为形式主义时犯错误 - 您可能think you proved one thing, when actually you proved another - 或者您可能会发现自己正在进行类型理论研究为了形成一个想法。
答案 1 :(得分:19)
这是任何规范语言(甚至英语)的问题,而不仅仅是依赖类型。你自己的帖子就是一个很好的例子:它包含一个非正式的"排序函数"只需要对结果进行排序,不你想要什么(\xs -> []
符合条件)。参见例如来自Twan van Laarhoven博客的this post。
答案 2 :(得分:14)
我认为反过来说:良好类型的程序无法证明是无意义的(假设系统是一致的),而规范可能不一致或只是愚蠢。所以它不是"如何确保这段代码反映我的柏拉图式的想法?",而是"如何确保我的想法有意义地投射到一个有充分根据的平面上纯粹的句法规则?"。如何确保你看到的鸟是一只模仿鸟[对于一些提供的模仿鸟的概念]?那么,研究鸟类并提高你成功的机会。但是always与humans一样,can't 100%肯定。
类型理论是一种通过引入正式规则来缓解人类思维不完美的方法,machine-checked proofs(它是一篇非常相关的论文)和其他东西,它们可以集中精力,从而简化问题(正如Brouwer所说:"数学只不过是,而不仅仅是我们思考的确切部分"),但是你不能期望任何工具能够让你的思想变得更好#34;正确"因为没有统一的正确概念。 Iow,没有办法正式连接非正式和正式:非正式就像是在IO
monad里面 - 没有逃脱。
所以它不是"这种语法是否反映了我非常精确的语义?",而是"我可以将原始语义附加到这种结构严谨的语法中吗?" 。程序是适当的物质对象,而想法是繁琐的近似,只能按照惯例成为适当的物质对象。因此,我们使用惯例形成一些基础,然后我们只相信它,因为信任所有众多想法的一小部分而不是所有想法更为明智。
答案 3 :(得分:7)
正式方法可以做的一件事,我认为其他人没有涉及的是帮助将简单的事物与更复杂的事物联系起来。您可能无法确切知道如何准确指定Set
数据结构的行为方式,但如果您可以根据排序列表编写简单版本,则可以证明基于平衡搜索树的您喜欢的版本与它正确地通过toList
函数。也就是说,您可以使用正式方法将您对排序列表的信心转移到平衡搜索树。
答案 4 :(得分:6)
你如何证明数学是正确的?也就是说,你如何证明整数加法是计算苹果的正确方法,或者你如何证明真正的加法是增加权重的正确方法?在形式/数学和非正式/真实之间总是存在接口。它需要技巧和数学/物质品味来找到解决特定问题的适当形式。正式方法不会消除这种情况。
形式方法的价值是双重的:
除非您知道它实际满足的属性,否则您不会知道您的程序是否正确。在您知道您的排序例程是否“正确”之前,您首先必须知道它实际上做了什么。任何找出这种方法的程序都将是一种正式的方法(甚至是单元测试!),所以拒绝“正式方法”的人实际上只是将自己局限于可用方法的一小部分。
即使你知道如何找出一个程序实际上做了什么,人们也会在他们的数学推理中犯错误(我们不是理性生物,无论某些意识形态可能会声称);所以让机器检查我们是有帮助的。这与我们使用单元测试的原因相同 - 运行桌面检查并确保程序完成我们想要的操作是很好的。但让计算机进行检查并告诉我们结果是否正确有助于防止错误。让计算机检查我们关于程序行为的证据是完全相同的原因。
答案 5 :(得分:2)
派对迟到了,但是AFAICT,还没有人提到另一个重要方面:在程序验证的背景下,规范中的错误并不总是太可怕,因为你可以使用代码检查规范。
IOW,证明并没有说“代码是对的”,但“代码和规范是相互一致的”。因此,为了使规范中的错误不被注意,它必须是以下之一:
正如其他人所指出的那样:测试的问题是一样的。
答案 6 :(得分:1)
假设您的函数不是顶级函数,但是被其他人用作某个模块的一部分,它也具有正确性证明。后者必须使用函数的正确性证明,如果不好,模块将无法编译。模块本身仍然可能有错误,但不再是你的问题了。