我希望直接从locale
定义生成代码,而无需解释。例如:
(* A locale, from the code point of view, similar to a class *)
locale MyTest =
fixes L :: "string list"
assumes distinctL: "distinct L"
begin
definition isInL :: "string => bool" where
"isInL s = (s ∈ set L)"
end
实例化MyTest
的假设是可执行的,我可以为它们生成代码
definition "can_instance_MyTest L = distinct L"
lemma "can_instance_MyTest L = MyTest L"
by(simp add: MyTest_def can_instance_MyTest_def)
export_code can_instance_MyTest in Scala file -
我可以定义一个函数来执行任意isInL
的{{1}}定义。
MyTest
但是,代码导出失败:
definition code_isInL :: "string list ⇒ string ⇒ bool option" where
"code_isInL L s = (if can_instance_MyTest L then Some (MyTest.isInL L s) else None)"
lemma "code_isInL L s = Some b ⟷ MyTest L ∧ MyTest.isInL L s = b"
by(simp add: code_isInL_def MyTest_def can_instance_MyTest_def)
为什么我要做这样的事情?
我在export_code code_isInL in Scala file -
No code equations for MyTest.isInL
的上下文中使用了locale
,例如here但有限。测试图表是否有效很容易。现在我想将我的图算法的代码导出到Scala中。当然,代码应该在任意有效图上运行。
我正在考虑类似于这样的Scala类比:
valid_graph
答案 0 :(得分:2)
解决此问题的一种方法是使用不变量进行数据类型细化(参见isabelle doc codegen
第3.3节)。因此,有效性假设(在您的情况下为distinct L
)可以移动到新类型中。请考虑以下示例:
typedef 'a dlist = "{xs::'a list. distinct xs}"
morphisms undlist dlist
proof
show "[] ∈ ?dlist" by auto
qed
这定义了一个新类型,其元素都是具有不同元素的列表。我们必须为代码生成器明确设置这种新类型。
lemma [code abstype]: "dlist (undlist d) = d"
by (fact undlist_inverse)
然后,在语言环境中我们假设“免费”(因为新类型的每个元素都保证它;但是,在某些时候,我们必须将一组基本操作从具有不同元素的列表提升到{{1 }}为s)。
'a dlist
此时,我们能够向代码生成器提供(无条件)方程式。
locale MyTest =
fixes L :: "string dlist"
begin
definition isInL :: "string => bool" where
"isInL s = (s ∈ set (undlist L))"
end
答案 1 :(得分:0)
我找到了一种方法,感谢克里斯的提示。
定义一个函数来测试先决条件/假设以实例化MyTest
definition "can_instance_MyTest L = distinct L"
命令term MyTest
显示MyTest
属于string list => bool
类型,
这意味着MyTest
是一个带谓参数的谓词,并测试此参数是否满足MyTest
的假设。
我们引入了一个代码方程([code]
),用可执行实例测试程序替换MyTest
。
代码生成器现在可以生成例如MyTest [a,b,c]
lemma [code]: "MyTest = can_instance_MyTest"
by(simp add:fun_eq_iff MyTest_def can_instance_MyTest_def)
export_code MyTest in Scala file -
我们屈服(我将List[Char]
替换为String
以提高可读性):
def can_instance_MyTest[A : HOL.equal](l: List[A]): Boolean =
Lista.distinct[A](l)
def myTest: (List[String]) => Boolean =
(a: List[String]) => can_instance_MyTest[String](a)
更易读的伪代码:
def myTest(l: List[String]): Boolean = l.isDistinct
现在我们需要isInL
的可执行代码。我们使用预定义的常量undefined
。如果L
不明显,此代码会抛出异常。
definition code_isInL :: "string list ⇒ string ⇒ bool" where
"code_isInL L s = (if can_instance_MyTest L then s ∈ set L else undefined)"
export_code code_isInL in Scala file -
我们屈服:
def code_isInL(l: List[String], s:String): Boolean =
(if (can_instance_MyTest[String](l)) Lista.member[String](l, s)
else sys.error("undefined"))*)
我们只需要证明code_isInL
是正确的:
lemma "b ≠ undefined ⟹ code_isInL L s = b ⟷ MyTest L ∧ MyTest.isInL L s = b"
by(simp add: code_isInL_def MyTest_def can_instance_MyTest_def MyTest.isInL_def)
(* Unfortunately, the other direction does not hold. The price of undefined. *)
lemma "¬ MyTest L ⟹ code_isInL L s = undefined"
by(simp add: code_isInL_def can_instance_MyTest_def MyTest_def)