我怎样才能说出Isabelle / HOL中不符合排序约束的引理?
要解释为什么这是有意义的,请考虑以下示例理论:
theory Test
imports Main
begin
class embeddable =
fixes embedding::"'a ⇒ nat"
assumes "inj embedding"
lemma OFCLASS_I:
assumes "inj (embedding::'a⇒_)"
shows "OFCLASS('a::type,embeddable_class)"
apply intro_classes by (fact assms)
instantiation nat :: embeddable begin
definition "embedding = id"
instance
apply (rule OFCLASS_I) unfolding embedding_nat_def by simp
end
end
该理论定义了一种类型“嵌入式”,其中一种类型参数为“嵌入”。 (基本上,embeddable类使用显式枚举来表示可数数字,但我选择它只是为了得到一个非常简单的例子。)
为了简化类型类的实例证明,该理论陈述了一个辅助引理OFCLASS_I
,它显示了OFCLASS(...,embeddable)
形式的目标。然后可以使用此引理来解决instance
产生的证明义务。
首先,为什么我甚至想要那个? (在目前的理论中,apply (rule OFCLASS_I)
与内置apply intro_classes
的作用相同,因此没用。)在更复杂的情况下,这种引理有两个原因:
intro_classes
是有问题的,因为intro_classes
的子目标数量可能会有所不同,具体取决于先前已执行的实例证明。 (像OFCLASS_I
这样的引理有一个稳定的,控制良好的子目标。)然而,上述理论在Isabelle / HOL(2015或2016-RC1)中均无效,因为引理不进行类型检查。不满足排序约束“embedding ::(_ :: embeddable => _)”。但是,这种类型的约束并不是逻辑必然(它不是由逻辑内核强制执行,而是由更高级别强制执行)。
那么,是否有一种说明上述理论的简洁方法? (我在答案中给出了一个有点丑陋的解决方案,但我正在寻找更清洁的东西。)
答案 0 :(得分:0)
可以在ML级暂时禁用排序约束的检查,然后重新激活。 (请参阅下面的完整示例。)但该解决方案看起来非常像黑客。我们必须在上下文中更改排序约束,并记得在之后恢复它们。
theory Test
imports Main
begin
class embeddable =
fixes embedding::"'a ⇒ nat"
assumes "inj embedding"
ML {*
val consts_to_unconstrain = [@{const_name embedding}]
val consts_orig_constraints = map (Sign.the_const_constraint
@{theory}) consts_to_unconstrain
*}
setup {*
fold (fn c => fn thy => Sign.add_const_constraint (c,NONE) thy) consts_to_unconstrain
*}
lemma OFCLASS_I:
assumes "inj (embedding::'a⇒_)"
shows "OFCLASS('a::type,embeddable_class)"
apply intro_classes by (fact assms)
(* Recover stored type constraints *)
setup {*
fold2 (fn c => fn T => fn thy => Sign.add_const_constraint
(c,SOME (Logic.unvarifyT_global T)) thy)
consts_to_unconstrain consts_orig_constraints
*}
instantiation nat :: embeddable begin
definition "embedding = id"
instance
apply (rule OFCLASS_I) unfolding embedding_nat_def by simp
end
end
这个理论被Isabelle / HOL接受。该方法适用于更复杂的设置(我已多次使用它),但我更喜欢更优雅的设置。
答案 1 :(得分:0)
以下是一个不同的解决方案,不需要"清理"在证明引理之后(this answer需要"修复"之后的排序约束)。
我的想法是定义一个新的常量(在我的例子中为embedding_UNCONSTRAINED
),它是原始排序约束常量(embedding
)的副本,除了没有排序约束(使用{{1以下命令)。然后使用local_setup
代替embedding_UNCONSTRAINED
来说明引理。但是通过添加属性embedding
,实际存储的引理使用常量[unfolded embedding_UNCONSTRAINED_def]
而没有排序约束。
这种方法的缺点是,在引证的证明期间,我们永远不能明确地写出包含embedding
的任何术语(因为这会添加不需要的排序约束)。但是,如果我们需要声明包含embedding
的子目标,我们可以始终使用embedding
说明它,然后使用embedding_UNCONSTRAINED
将其转换为unfolding embedding_UNCONSTRAINED
。
embedding