类型类实例化中的现有常量(例如构造函数)

时间:2015-06-10 14:21:19

标签: typeclass isabelle

考虑这个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

如何使用现有常量实例化类型类而不是定义新类型?

1 个答案:

答案 0 :(得分:3)

Isabelle中的类型类实例化总是为类型类的参数引入新的常量。因此,您不能说plus(书面中缀为+)与Plus相同。但是,您可以采用相反的方式,即首先实例化类型类,然后稍后将类型类上的操作声明为数据类型的构造函数。

可以在理论Extended_Nat中找到一个这样的案例,其中类型enat是通过typedef手动构造的,然后实例化无限类型类,最后{{1}使用enat将两个构造函数声明为数据类型。但是,这是一个非简单的非递归数据类型,没有类型变量。如果是您的表达示例,我建议您执行以下操作:

  1. 使用old_rep_datatype定义类型expr_aux

  2. 使用datatype expr_aux = Const_aux nat | Plus_aux expr_aux expr_auxexprexpr_aux定义为typedef expr = "UNIV :: expr_aux set"的类型副本。

  3. 使用提升包将构造函数setup_lifting type_definition_expr提升到Const_auxexpr

  4. 实例化类型类lift_definition Const :: "nat => expr" is Const_aux .

  5. plus
    1. instantiation expr :: plus begin lift_definition plus_expr :: "expr => expr => expr" is Plus_aux . instance .. end 注册为包含expr的数据类型和相应的证明(使用old_rep_datatype expr Const "plus :: expr => _")。

    2. 定义transfer

    3. 显然,这非常乏味。如果您只想在函数中使用模式匹配,则可以使用abbreviation Plus :: "expr => expr => expr" where "Plus == plus"命令在实例化后将构造函数free_constructorConst注册为plus :: expr => expr => expr的新构造函数。如果你然后添加“Plus = plus”作为简单规则,这应该与繁琐的方式一样好。然而,我不知道各种包(特别是语法语法)如何处理构造函数的重新注册。