我想创建一个形状像旧的数据类型,但是(与使用type_synonym
不同)它应该被认为在其他理论中是独特的。
我的激励示例:我正在从列表中创建堆栈数据类型。我不希望我的其他理论将我的stack
视为list
,因此我可以对其执行自己的简化规则,但我发现的唯一解决方案是以下:
datatype 'a stk = S "'a list"
...
primrec index_of' :: "'a list => 'a => nat option"
where "index_of' [] b = None"
| "index_of' (a # as) b = (
if b = a then Some 0
else case index_of' as b of Some n => Some (Suc n) | None => None)"
primrec index_of :: "'a stk => 'a => nat option"
where "index_of (S as) x = index_of' as x"
...
lemma [simp]: "index_of' del v = Some m ==> m <= n ==>
index_of' (insert_at' del n v) v = Some m"
<proof>
lemma [simp]: "index_of del v = Some m ==> m <= n ==>
index_of (insert_at del n v) v = Some m"
by (induction del, simp)
它有效,但这意味着我的stack
理论膨胀并充满了冗余:每个函数都有第二个版本剥离构造函数,每个定理都有第二个版本(证明是总是 by (induction del, simp)
,这让我觉得这是我在某个地方做太多工作的迹象。)
这里有什么有用的吗?
答案 0 :(得分:3)
您想使用typedef
。
声明
typedef 'a stack = "{xs :: 'a list. True}"
morphisms list_of_stack as_stack
by auto
引入了一个新类型,包含所有列表,以及'a stack
和'a list
之间的函数以及一堆定理。以下是它们的选择(您可以在show_theorems
命令后使用typedef
查看所有内容):
theorems:
as_stack_cases: (⋀y. ?x = as_stack y ⟹ y ∈ {xs. True} ⟹ ?P) ⟹ ?P
as_stack_inject: ?x ∈ {xs. True} ⟹ ?y ∈ {xs. True} ⟹ (as_stack ?x = as_stack ?y) = (?x = ?y)
as_stack_inverse: ?y ∈ {xs. True} ⟹ list_of_stack (as_stack ?y) = ?y
list_of_stack: list_of_stack ?x ∈ {xs. True}
list_of_stack_inject: (list_of_stack ?x = list_of_stack ?y) = (?x = ?y)
list_of_stack_inverse: as_stack (list_of_stack ?x) = ?x
type_definition_stack: type_definition list_of_stack as_stack {xs. True}
这里的?x ∈ {xs. True}
假设很无聊,但您可以在那里指定所有列表的子集,例如:如果您的堆栈永远不会为空,并确保该属性适用于所有类型的类型级别。
type_definition_stack
定理与lifting
包一起使用很有用。声明后
setup_lifting type_definition_stack
你可以通过给出列表中的定义来定义堆栈上的函数,并通过证明它们在列表方面的等效命题来证明涉及堆栈的定理;比手动处理转换函数容易得多。