考虑这个Isabelle代码
theory Scratch imports Main begin
datatype Expr = Const nat | Plus Expr Expr
实例化plus
类型类以获得Plus
构造函数的良好语法是非常合理的:
instantiation Expr :: plus
begin
definition "plus_Exp = Plus"
instance..
end
但是现在,+
和Plus
仍然是单独的常量。特别是,我不能(轻松)在函数定义中使用+
,例如
fun swap where
"swap (Const n) = Const n"
| "swap (e1 + e2) = e2 + e1"
将打印
Malformed definition:
Non-constructor pattern not allowed in sequential mode.
⋀e1 e2. swap (e1 + e2) = e2 + e1
如何使用现有常量实例化类型类而不是定义新类型?
答案 0 :(得分:3)
Isabelle中的类型类实例化总是为类型类的参数引入新的常量。因此,您不能说plus
(书面中缀为+
)与Plus
相同。但是,您可以采用相反的方式,即首先实例化类型类,然后稍后将类型类上的操作声明为数据类型的构造函数。
可以在理论Extended_Nat中找到一个这样的案例,其中类型enat
是通过typedef
手动构造的,然后实例化无限类型类,最后{{1}使用enat
将两个构造函数声明为数据类型。但是,这是一个非简单的非递归数据类型,没有类型变量。如果是您的表达示例,我建议您执行以下操作:
使用old_rep_datatype
定义类型expr_aux
。
使用datatype expr_aux = Const_aux nat | Plus_aux expr_aux expr_aux
和expr
将expr_aux
定义为typedef expr = "UNIV :: expr_aux set"
的类型副本。
使用提升包将构造函数setup_lifting type_definition_expr
提升到Const_aux
:expr
实例化类型类lift_definition Const :: "nat => expr" is Const_aux .
:
plus
将instantiation expr :: plus begin
lift_definition plus_expr :: "expr => expr => expr" is Plus_aux .
instance ..
end
注册为包含expr
的数据类型和相应的证明(使用old_rep_datatype expr Const "plus :: expr => _"
)。
定义transfer
显然,这非常乏味。如果您只想在函数中使用模式匹配,则可以使用abbreviation Plus :: "expr => expr => expr" where "Plus == plus"
命令在实例化后将构造函数free_constructor
和Const
注册为plus :: expr => expr => expr
的新构造函数。如果你然后添加“Plus = plus”作为简单规则,这应该与繁琐的方式一样好。然而,我不知道各种包(特别是语法语法)如何处理构造函数的重新注册。