我尝试为自定义数据类型创建自定义线性订单失败,以下是我的代码:
theory Scratch
imports Main
begin
datatype st = Str "string"
fun solf_str_int:: "string ⇒ int" where
"solf_str_int str = (if (size str) > 0
then int(nat_of_char (hd str) + 1) + 100 * (solf_str_int (tl str))
else 0)"
fun soflord:: "st ⇒ st ⇒ bool" where
"soflord s1 s2 = (case s1 of Str ss1 ⇒ (case s2 of Str ss2 ⇒
(solf_str_int ss1) ≤ (solf_str_int ss2)))"
instantiation st :: linorder
begin
definition nleq: "less_eq n1 n2 == soflord n1 n2"
definition neq: "eq n1 n2 == (n1 ≤ n2) ∧ (n2 ≤ n1)"
definition nle: "less n1 n2 == (n1 ≤ n2) ∧ (¬(n1 = n2))" (* ++ *)
instance proof
fix n1 n2 x y :: st
show "n1 ≤ n1" by (simp add:nleq split:st.split)
show "(n1 ≤ n2) ∨ (n2 ≤ n1)" by (simp add:nleq split:st.split) (*why is 'by ()' highlited?*)
(*this fail if I comment line ++ out*)
show "(x < y) = (x ≤ y ∧ (¬ (y ≤ x)))" by (simp add:nleq neq split:node.split)
qed
end
end
标有(* ++ *)的定义不正确,如果删除它,最后一个节目会出现问题。
如何更正证明? 为什么第二个最后一个节目部分突出显示?
答案 0 :(得分:2)
在less_eq
的情况下定义类型类(less
和linorder
)的操作时,只有在推断类型的情况下才能使用重载操作的名称。该操作完全匹配正在定义的重载实例。特别是,如果结果太过笼统,那么这种类型就不是专门的。
less_eq
的定义有效,因为soflord
将n1
和n2
的类型限制为st
,因此less_eq
与类型一起使用st => st => bool
,这正是这里所需要的。对于less
,类型推断计算最常规的类型'b :: ord => 'b => bool
。由于这不是预期的类型st => st => bool
,Isabelle并不认为该定义是重载操作的定义,因此抱怨您想要完全重新定义现有操作。如果您根据需要限制类型,则定义按预期工作。
definition nle: "less n1 (n2 :: st) == (n1 ≤ n2) ∧ (¬(n1 = n2))"
但是,您的定义未在st
上定义线性顺序。问题是违反了反对称性。例如,两个字符串Str ''d''
和Str [Char Nibble0 Nibble0, Char Nibble0 Nibble0]
(即,在代码点0
由两个字符组成的字符串)在您的订单中是“等效的”,尽管它们是不同的值。您也尝试在st
上定义相等性,但在高阶逻辑中,不能定义相等性。它取决于您构建类型的方式。如果你真的想要根据你的订单识别相同的字符串,你必须首先构造一个商,例如,使用商包。
by(simp ...)
的紫色高亮表示证明方法simp
仍在运行。在您的情况下,它不会终止,因为simp
将继续展开solf_str_int
的定义等式:它的右侧包含左侧的实例。我建议您通过=
左侧的模式匹配来定义函数。然后,只有当它们可以消耗模式时才使用这些方程。因此,您必须自己触发案例区分(例如使用cases
),但您也可以更好地控制自动化策略。