Isabelle的代码生成:容器的抽象引理?

时间:2013-04-16 14:43:32

标签: code-generation isabelle

我正在尝试代码生成器。我的理论包含一个编码不变量的数据类型:

typedef small = "{x::nat. x < 10}" morphisms to_nat small
  by (rule exI[where x = 0], simp)

definition "is_one x ⟷ x = small 1"

现在我要导出is_one的代码。似乎我首先必须为代码生成器设置数据类型,如下所示:

code_datatype small

instantiation small :: equal
begin
  definition "HOL.equal a b ⟷ to_nat a = to_nat b" 
  instance
  apply default
  unfolding equal_small_def
  apply (rule to_nat_inject)
  done
end

lemma [code abstype]: "small (to_nat x) = x" by (rule to_nat_inverse)

现在我能够为is_one定义一个不违反抽象的代码方程式:

definition [code del]:"small_one = small 1"
declare is_one_def[code del]
lemma [code]: "is_one x ⟷ x = small_one" unfolding is_one_def small_one_def..
lemma [code abstract]: "to_nat small_one = 1"
  unfolding small_one_def by (rule small_inverse, simp)

export_code is_one in Haskell file -

问题1:我可以避免将small_one的定义从is_one中删除吗?

现在我有一个小项目的复合值:

definition foo :: "small set list" where "foo = [ {small (10-i), small i} . i <- [2,3,4] ]"

在那种形式下,我无法使用它导出代码(“代码方程foo中的抽象违规......”)。

问题2:如何为这样的值定义[code abstract]引理?似乎代码生成器不接受map to_nat foo = ...形式的引理。

2 个答案:

答案 0 :(得分:3)

对于由code_abstract声明的不变量的类型,例如small,没有代码等式可能包含抽象函数small。因此,如果您希望is_one中的等式测试在small类型上表达,则必须为small 1定义一个常量,并首先使用to_nat证明相应的代码等式。这就是你所做的。但是,在表示类型nat上使用相等会更容易,即内联实现equal_class.equal;那么,您也不需要为equal实例化small

lemma is_one_code [code]: "is_one x ⟷ to_nat x = 1"
by(cases x)(simp add: is_one_def small_inject small_inverse)

lifting包会自动为您完成大部分操作:

setup_lifting type_definition_small
lift_definition is_one :: "small => bool" is "%x. x = 1" ..
export_code is_one in SML file -

不幸的是,代码生成器不支持涉及small set list中的抽象类型的复合返回类型。如Data Refinement in Isabelle/HOL, sect. 3.2中所述,您必须将类型small set list包装为其自己的类型构造函数small_set_list,并使用类型foo定义small_set_list。然后将small_set_list类型表示为nat set list,其中包含不变list_all (%A. ALL x:A. x < 10)

答案 1 :(得分:0)

除了安德烈亚斯的解释和全面的解决方案,我找到了一种避免引入新类型的解决方法。假设foo未在许多地方使用,例如,仅在

中使用
definition "in_foo x = (∀s ∈ set foo. x ∈ s)"

尝试导出in_foo的代码会导致“抽象违规”错误。但是使用程序优化,我可以避免有问题的代码:

我使用code_thms了解foo的使用方式,并发现它被用作list_all (op ∈ ?x) foo。现在我重写foo的这种特殊用法,而没有提到small

lemma [code_unfold]:
  "list_all (op ∈ x) foo ⟷
    list_all (op ∈ (to_nat x))  [ {(10-i), i} . i <- [2, 3, 4] ]"
  unfolding foo_def by (auto simp add: small_inverse small_inject)

(如果我使用foo定义lift_definition,则apply transfer之后的证明会更简单。)

在此转换之后,基本上捕获foo的所有成员都满足small的不变量,代码导出按预期工作:

export_code in_foo in Haskell file -