假设我写了一个用于反转列表的函数。我想用value
命令测试它,只是为了向自己保证我可能做对了。但输出看起来很可怕:
value "reverse [1,8,3]"
> "[1 + 1 + 1, 1 + 1 + (1 + 1) + (1 + 1 + (1 + 1)), 1]" :: "'a list"
如果我告诉Isabelle将这些数字字符视为自然,那么输出会更糟:
value "reverse [1::nat,8,3]"
> "[Suc (Suc (Suc 0)), Suc (Suc (Suc (Suc (Suc (Suc (Suc (Suc 0))))))), Suc 0]" :: "nat list"
有时我会求助于使用字符串,但对于所有这些撇号而言,这看起来有点滑稽:
value "reverse [''1'',''8'',''3'']"
> "[''3'', ''8'', ''1'']" :: "char list list"
我是否可以指示Isabelle的漂亮打印机将Suc (Suc (Suc 0))
打印为3
,依此类推?也许通过给syntax
或translations
命令提供一些神奇的咒语?
这是我的完整示例,如果您想将其粘贴到Isabelle中:
theory Scratch imports Main begin
fun reverse where
"reverse [] = []"
| "reverse (x#xs) = reverse xs @ [x]"
value "reverse [1,8,3]"
value "reverse [1::nat,8,3]"
value "reverse [''1'',''8'',''3'']"
end
答案 0 :(得分:5)
简答:我的第一个想法是使用类型int
,因为(与nat
不同),其代码生成器设置默认使用二进制数字表示。
如果您不想对"~~/src/HOL/Library/Code_Target_Nat"
类型使用Suc
表示形式,那么导入nat
也是一个好主意。
说明: Isabelle中的数字使用Num.thy
中定义的构造函数进行编码;例如5
是numeral (Bit1 (Bit0 One))
的缩写。此处One
,Bit0
和Bit1
是num
类型的构造函数。 numeral
已重载,适用于1
和关联+
的任何类型。以下是numeral
的代码方程式:
lemma numeral_code [code]:
"numeral One = 1"
"numeral (Bit0 n) = (let m = numeral n in m + m)"
"numeral (Bit1 n) = (let m = numeral n in m + m + 1)"
如果我们为5::'a::numeral
生成代码,则类型1
上的+
和'a
会被视为未解释的常量,因此它们会保留在输出中:{{1} }。
为(1 + 1) + (1 + 1) + 1
生成代码的工作方式相同,只是我们做的代码5::nat
和1
代码+
, nat
。因此,Suc
会进一步缩短为(1 + 1) + (1 + 1) + 1
。
类型Suc (Suc (Suc (Suc (Suc 0))))
的工作方式不同。 int
中的代码生成器设置使用类型Int.thy
的三个构造函数:int
和Pos
类型Neg
,以及num => int
。 0
声明会导致代码生成期间code_abbrev
类型numeral
的每次出现都被num => int
替换。代码运行后,然后在Isabelle显示结果之前将Pos
变回Pos
。因此numeral
评估为5::int
。
特殊代码设置理论: 5
包含一些用于自定义数字代码生成的不同理论。
src/HOL/Library
告诉代码生成器使用目标语言(例如SML或Haskell)的内置数字类型"~~/src/HOL/Library/Code_Target_Nat"
。例如,nat
通常被翻译为SML 5::nat
;但是,加载此库后,它将在SML中转换为numeral (Bit1 (Bit0 One))
。 5
的结果随后被转换回伊莎贝尔数字表示。
value
是相同的,但对于"~~/src/HOL/Library/Code_Target_Int"
类型而不是int
。
nat
只需加载前两个库。它只会影响"~~/src/HOL/Library/Code_Target_Numeral"
和nat
类型,而不会影响类int
中的任何其他类型。
numeral
使用与"~~/src/HOL/Library/Code_Binary_Nat"
的默认代码设置相同的样式配置nat
:使用构造函数int
和0
以及{{{ 1}}声明。使用此库,nat_of_num::num => nat
也会返回code_abbrev
。
答案 1 :(得分:2)
注意:我希望我的回答并不能阻止Brian Huffman或Florian Haftmann给出答案。如果确实如此,那将是一件坏事。希望我只是做一些gofer工作来设置它们中的任何一个。
简答1:相关的邮件列表电子邮件是Re: [isabelle] value no longer pretty-prints numbers of type nat。
简答2: nat
的解决方案是导入"~~/src/HOL/Library/Code_Target_Nat"
。因为我不清楚numeral
和num
如何在低级别与HOL完全联系的细节,我给你的解决方案不一定是好的和最终的溶液
我的答案很大一部分是在Brian Huffman或Florian Haftmann来到这里之前,Num.thy的作者,#34;我也对此感兴趣,因为它与numeral
有关,numeral
是HOL的一个重要组成部分。关于使用nat
的错综复杂的信息越多,越好#34;
基本上,他们为Isabelle2013-1做了设计选择更改,即numeral
和declare[[show_sorts=true]]
的默认值以后继形式表示。这就是邮件列表电子邮件的内容。
如果您使用value "reverse [1,8,3]"
,则会看到您的numeral
正在使用类型类numeral
。我之所以提到这一点,是因为我一直在努力学习nat
,甚至使用具体类型,例如int
和44
,使用常量例如5
和numeral
涉及nat
,至少是输入。即使使用numeral
这样的具体类型,simp
也可以参与正在使用的nat
规则。
在说出更多内容之前,为value "reverse [1::nat,8,3]"
获得良好"~~/src/HOL/Library/Code_Target_Nat"
输出的一种方法是再次使用以下导入:
value "reverse [1,8,3]"
我对您的问题感兴趣的原因是因为这只是Andreas Lochbihler在该电子邮件中看到的即插即用解决方案。
我无法通过导入"~~/src/HOL/Library/Code_Target_Numeral"
让numeral
不使用1的总和:
numeral
所以,我想知道如何让lemma "(3::nat) = z"
using[[simp_trace, simp_trace_depth_limit=100, linarith_trace, rule_trace]]
using[[blast_trace, blast_stats]]
apply simp
oops
成为我们喜欢看的好形式。
无论如何,[1]SIMPLIFIER INVOKED ON THE FOLLOWING TERM:
3 = z
[1]Procedure "Num.reorient_numeral" produced rewrite rule:
?a1 = ?b1 ≡ ?b1 = ?a1
[1]Applying instance of rewrite rule
?a1 = ?b1 ≡ ?b1 = ?a1
[1]Rewriting:
3 = z ≡ z = 3
是使用数字常量的核心。考虑一下:
Num
simp追踪的一部分是:
{{1}}
如果你看一下涉及数字常数的简单跟踪,你会发现{{1}}规则显示了很多,这些规则来自Num.thy中最优秀的规则。