如何使用反驳来指导Haskell中的类型检查器?
填充以下程序中的孔是否需要非建设性方法?如果是,如果如何使用反驳来指导Haskell中的类型检查器?,haskell,types,dependent-type,theorem-proving,Haskell,Types,Dependent Type,Theorem Proving,填充以下程序中的孔是否需要非建设性方法?如果是,如果x:~:y可判定,是否仍然是这种情况 更一般地说,我如何使用反驳来指导类型检查器 (我知道我可以通过将Choose定义为GADT来解决这个问题,我特别要求类型族) {-#语言数据类型} {-#语言类型族{-} {-#语言类型运算符{-} 模块命题质量,其中 导入Data.Type.Equality 导入数据。无效 类型族选择x y何处 选择x=1 选择x u=2 lem::(x:~:y->Void)->选择x:y:~:2 lem反驳=_ 如果你
x:~:y
可判定,是否仍然是这种情况
更一般地说,我如何使用反驳来指导类型检查器
(我知道我可以通过将Choose
定义为GADT来解决这个问题,我特别要求类型族)
{-#语言数据类型}
{-#语言类型族{-}
{-#语言类型运算符{-}
模块命题质量,其中
导入Data.Type.Equality
导入数据。无效
类型族选择x y何处
选择x=1
选择x u=2
lem::(x:~:y->Void)->选择x:y:~:2
lem反驳=_
如果你努力实现一个功能,你可以说服自己
这是不可能的。如果你不相信,可以提出论点
更正式:我们详尽地列举程序,发现没有一个是可能的。事实上,只有六打有意义的案例需要考虑。
我想知道为什么不经常提出这一论点
完全不准确的总结:
- 第一幕:寻找证据很容易
- 第二幕:依赖类型也一样
- 第三幕:Haskell仍然适合编写依赖类型的程序
lem = (exp)
对于某些表达式(exp)
。现在我们只需要找到一个表达式
查看所有在Haskell中创建表达式的可能方式:
(这不包括扩展,读者的练习)
它可以将一页放在一列中,所以一开始就没有那么大。
此外,它们中的大多数是用于某种形式的功能或应用的糖
模式匹配;我们还可以使用字典来删除类型类
通过,我们剩下一个小得可笑的lambda演算:
- lambdas,
\x->…
- 模式匹配,
大小写。。。属于…
- 函数应用程序,
fx
- 构造函数,
(包括整数文本)C
- 常量,
(对于不能按照上述构造编写的原语,因此需要各种内置(c
)以及FFI(如果有)seq
- 变量(由lambda和cases绑定)
未定义
,未安全性
这样的黑魔法常量,
unsafePerformIO
使一切崩溃(任何类型都有人居住,例如
其中一些,类型系统是不健全的),并留下白魔法
当前理论论证可通过
资金充足的论文)
我们也可以合理地假设我们想要一个不涉及递归的解决方案
(以消除噪音,如lem=lem
,如果您觉得无法解决,则fix
)
之前的部分),并且实际上有一个标准形式,或者最好是一个
关于βη-等价的标准形式。换言之,我们改进并
检查一组可能的解决方案,如下所示
有一个函数类型,因此我们可以假设它的定义以lambda开头:lem::->
-- Any solution lem = (exp) -- is η-equivalent to a lambda lem = \refutation -> (exp) refutation -- so let's assume we do have a lambda lem = \refutation -> _hole
- 它可能是一个构造器,
然后必须是
,但没有证据表明Refl
上下文(这里我们可以形式化和枚举类型等式) typechecker知道并可以派生或生成强制的语法 (等式证明)明确并继续玩这个证明搜索游戏 所以这不需要进行类型检查:在中选择了x y~2
也许有某种方法可以构造平等证明,但是 表达式将从另一个开始,这将是另一个 证据的情况lem = \refutation -> Refl
- 它可能是构造函数的某个应用程序
,或者 变量cx1x2…
(是否应用);但这是不可能的 好的类型,它必须以某种方式产生一个反驳
,而(:~:)
实际上是 唯一的办法Refl
- 或者它可能是一个
。WLOG,左侧没有嵌套的案例
,也没有 构造函数,因为表达式在这两种情况下都可以简化:大小写
因此,最后一个子类是可变情况:-- Any left-nested case expression case (case (e) of { C x1 x2 -> (f) }) { D y1 y2 -> (g) } -- is equivalent to a right-nested case case (e) of { C x1 x2 -> case (f) of { D y1 y2 -> (g) } } -- Any case expression with a nested constructor case (C u v) of { C x1 x2 -> f x1 x2 } -- reduces to f u v
我们必须构造一个lem = \refutation -> case refutation (_hole :: x :~: y) of {}
。我们列举了填写表格的方法x:~:y
。要么是\u再次打开孔
,但没有证据,要么是 (跳过一些步骤){}的案例反驳(_另一个例子::x:~:y), 我们手上有无限的血统,这也是荒谬的。 另一个可能的论点是,我们可以拉出Refl
从应用程序中删除此案例案例
-- Any application to a case f (case e of C x1 x2 -> g x1 x2) -- is equivalent to a case with the application inside case e of C x1 x2 -> f (g x1 x2)
(x:~:y->Void)->选择x y:~:2
。QED
要阅读更多关于这个主题的内容,我想应该读一本关于lambda微积分的课程/书籍
直到简单类型lambda演算的规范化证明给出
您可以从基本工具开始。以下论文包含一个
第一部分是关于这个问题的介绍,但不可否认,我的判断能力很差
这些材料的难度:,
加布里埃尔·谢勒
请随意推荐更多的资源和文献
二,。修正命题并用依赖类型证明它 你最初的直觉认为这应该是一个有效的命题 这是绝对有效的。我们如何修正它,使其可证明 从技术上讲,我们正在查看的类型是通过
对所有进行量化的:
forall x y. (x :~: y -> Void) -> Choose x y :~: 2
foreach x y. (x :~: y -> Void) -> Choose x y :~: 2
lem :: foreach x y. (x :~: y -> Void) -> Choose x y :~: 2
lem x y p = case x ==? u of
Left r -> absurd (p r) -- x ~ y, that's absurd!
Right Irrefl -> Refl -- x /~ y, so Choose x y = 2