展开/ simp对primrec类类实例化证明没有影响

时间:2014-01-27 03:47:07

标签: isabelle

直到几天前,我总是定义一个类型,然后直接证明了关于类型的定理。现在我尝试使用类型类。

问题

问题在于我无法为下面的cNAT类型myD实例化,而且它似乎是因为simp对抽象函数没有影响cNAT,我已使用primrec函数cNAT_myD制作了具体内容。由于instance proof之后发生的自动化,我只能猜测发生了什么。

问题

Q1:下面,在instantiation myD :: (type) cNAT语句中,您能告诉我如何完成证明,以及为什么我可以证明以下定理,但不能证明类型类证明,需要injective

theorem dNAT_1_to_1: "(dNAT n = dNAT m) ==> n = m"

assumes injective: "(cNAT n = cNAT m) ==> n = m"

Q2:这不是那么重要,但最底层是这句话:

instantiation myD :: (type) cNAT2

它涉及我试图实例化cNAT的另一种方式。你能告诉我为什么我Failed to refine any pending goal shows了吗?我在源代码中添加了一些注释来解释我为设置它所做的一些事情。我使用了这个稍微修改过的公式来满足要求injective

assumes injective: "!!n m. (cNAT2 n = cNAT2 m) --> n = m"

具体细节

我设计的datatype就是这个,这对某些人来说可能对我有用:(更新:好吧,也许是另一个例子。一个好的心理练习是我试着弄清楚我怎么能够除了'a myD list之外,[]内有一些内容。使用BNF,类似datatype_new 'a myD = myS "'a myD fset"的内容会向我发出警告,指出右边有一个未使用的类型变量 - 手边)

datatype 'a myD = myL "'a myD list"

类型类是这样的,它需要从nat'a的内射函数:

class cNAT =
  fixes cNAT :: "nat => 'a"
  assumes injective: "(cNAT n = cNAT m) ==> n = m"

dNAT:这种非类型的cNAT版本

fun get_myL :: "'a myD => 'a myD list" where
  "get_myL (myL L) = L"

primrec dNAT :: "nat => 'a myD" where
  "dNAT 0       = myL []"
 |"dNAT (Suc n) = myL (myL [] # get_myL(dNAT n))"

fun myD2nat :: "'a myD => nat" where
  "myD2nat (myL [])       = 0"
 |"myD2nat (myL (x # xs)) = Suc(myD2nat (myL xs))"

theorem left_inverse_1 [simp]:
  "myD2nat(dNAT n) = n"
apply(induct n, auto)
by(metis get_myL.cases get_myL.simps)

theorem dNAT_1_to_1:
  "(dNAT n = dNAT m) ==> n = m"
apply(induct n)
apply(simp) (*
  The simp method expanded dNAT.*)
apply(metis left_inverse_1 myD2nat.simps(1))
by (metis left_inverse_1)

cNAT:我无法实例化的类型类版本

instantiation myD :: (type) cNAT
begin
primrec cNAT_myD :: "nat => 'a myD" where
  "cNAT_myD 0       = myL []"
 |"cNAT_myD (Suc n) = myL (myL [] # get_myL(cNAT_myD n))"

instance
proof 
  fix n m :: nat
show "cNAT n = cNAT m ==> n = m"
  apply(induct n)
  apply(simp) (*
The simp method won't expand cNAT to cNAT_myD's definition.*)
  by(metis injective)+ (*
Metis proved it without unfolding cNAT_myD. It's useless. Goals always remain,
and the type variables in the output panel are all weird.*)
oops
end

cNAT2:无法优化show

处的任何待定目标
(*I define a variation of `injective` in which the `assumes` definition, the
  goal, and the `show` statement are exactly the same, and that strange `fails
  to refine any pending goal shows up.*)
class cNAT2 =
  fixes cNAT2 :: "nat => 'a"
  assumes injective: "!!n m. (cNAT2 n = cNAT2 m) --> n = m"

instantiation myD :: (type) cNAT2
begin
primrec cNAT2_myD :: "nat => 'a myD" where
  "cNAT2_myD 0       = myL []"
 |"cNAT2_myD (Suc n) = myL (myL [] # get_myL(cNAT2_myD n))"
instance
proof (*
  goal: !!n m. cNAT2 n = cNAT2 m --> n = m.*)
show 
  "!!n m. cNAT2 n = cNAT2 m --> n = m"

  (*Failed to refine any pending goal 
    Local statement fails to refine any pending goal
    Failed attempt to solve goal by exported rule:
      cNAT2 (n::nat) = cNAT2 (m::nat) --> n = m *)

1 个答案:

答案 0 :(得分:1)

您的函数cNAT在其结果类型中是多态的,但类型变量不会出现在参数中。这通常会导致类型推断计算出比您想要的更通用的类型。对于cNAT的情况,Isabelle推断出cNAT语句中show的两次出现nat => 'b'b排序cNAT },但他们在目标中的类型是nat => 'a myD。你可以在jEdit中通过 Ctrl - 在cNAT次出现时看到这个以检查类型。在ProofGeneral中,您可以使用using [[show_consts]]启用类型打印。

因此,您必须在show语句中明确约束类型,如下所示:

fix n m
assume "(cNAT n :: 'a myD) = cNAT m"
then show "n = m"

请注意,在!!语句中使用Isabelle的元连词==>show通常不是一个好主意,您最好使用fix / {对它们进行重新措辞{1}} / assume