Isabelle 我如何声明一个不考虑排序约束的引理(用于类的使用)

Isabelle 我如何声明一个不考虑排序约束的引理(用于类的使用),isabelle,Isabelle,如何在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_cl

如何在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
该理论定义了一个类型类“Embedded”,其中有一个类型参数“Embedded”。(基本上,Embeddeble类通过显式枚举来刻画可数数字,但我选择它只是为了有一个非常简单的示例。)

为了简化类型类的实例证明,该理论陈述了类I的辅助引理
,该引理显示了类(…,可嵌入)
形式的目标。这个引理可以用来解决
实例产生的证明义务

首先,我为什么要这样?(在目前的理论中,
apply(class_I的规则)
与内置的
apply intro_类
相同,因此是无用的。)在更复杂的情况下,有两个原因导致这样的引理:

  • 引理可以为类型类的实例化提供替代标准,从而简化后续证明
  • 引理可用于自动化(ML级)实例化。这里使用
    intro_类
    是有问题的,因为
    intro_类
    的子目标的数量可能会根据之前执行的实例证明而有所不同。(一个引理,比如I类的
    有一个稳定的、控制良好的子目标。)
然而,上述理论在Isabelle/HOL(2015或2016-RC1)中不起作用,因为引理不进行类型检查。排序约束“embedding::(::embeddable=>ux)”不满足。但是,这种类型的约束不是逻辑上必需的(它不是由逻辑内核强制执行的,而是由更高级别强制执行的)


那么,有没有一种清晰的方式来阐述上述理论?(我在回答中给出了一个有点难看的解决方案,但我正在寻找更干净的方法。)

可以在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

这一理论为伊莎贝尔/霍尔所接受。该方法适用于更复杂的环境(我已经多次使用过),但我更喜欢更优雅的方法。

以下是一种不同的解决方案,在证明引理后不需要“清理”(需要“修复”排序约束)

其思想是定义一个新常量(
embedding\u unconstrated
,在我的示例中),它是原始排序约束常量(
embedding
)的副本,但没有排序约束的情况除外(使用下面的
local\u setup
命令)。然后使用
embedding\u unconstraint
而不是
embedding
来表示引理。但是通过添加属性
[unfolded embedding\u unconstraint\u def]
实际存储的引理使用常量
embedding
,而不受排序约束

这种方法的缺点是,在证明引理的过程中,我们永远不能显式地编写任何包含
嵌入的术语(因为这将添加不需要的排序约束)。但是如果我们需要声明包含
嵌入
的子目标,我们总是可以使用
嵌入_unconstrated
声明它,然后使用,例如
展开嵌入_unconstrated
将其转换为
嵌入

theory Test
imports Main
begin

class embeddable = 
  fixes embedding::"'a ⇒ nat"
  assumes "inj embedding"

(* This does roughly:
   definition "embedding_UNCONSTRAINED == (embedding::('a::type)=>nat)" *)
local_setup {* 
  Local_Theory.define ((@{binding embedding_UNCONSTRAINED},NoSyn),((@{binding embedding_UNCONSTRAINED_def},[]),
      Const(@{const_name embedding},@{typ "'a ⇒ nat"}))) #> snd
*}

lemma OFCLASS_I [unfolded embedding_UNCONSTRAINED_def]:
  assumes "inj (embedding_UNCONSTRAINED::'a⇒_)"
  shows "OFCLASS('a::type,embeddable_class)"
apply intro_classes by (fact assms[unfolded embedding_UNCONSTRAINED_def])

thm OFCLASS_I (* The theorem now uses "embedding", but without sort "embeddable" *)

instantiation nat :: embeddable begin
definition "embedding = id"
instance
  apply (rule OFCLASS_I) unfolding embedding_nat_def by simp
end

end