我正在尝试代码生成器。我的理论包含一个编码不变量的数据类型:
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 = ...
形式的引理。
答案 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 -